Kero
Kero

Reputation: 1944

How to make a responsive nav-bar using Angular material 2?

I'm trying to create a navigation bar using Angular material 2 that collapses in small screens like mobile devices and tablets.

I was only able to find md-button but not md-menu-bar as was in Angular material.

Upvotes: 37

Views: 84255

Answers (8)

rjdkolb
rjdkolb

Reputation: 11838

The simplest way to create a responsive navbar with Material is use the Angular CLI schematics.

(If you get 'Collection "@angular/material" cannot be resolved' when running ng add @angular/material, see this)

Then use the generated component <app-my-nav></app-my-nav> Add the above tag to your main component

Responsive view on Desktop PC: Responsive view on Desktop PC

Responsive collapsed menu with low resolution: Responsive collapsed menu with low resolution

This was seen originally on Angular's blog.

Upvotes: 17

user2662006
user2662006

Reputation: 2294

Here is what I used to build my responsive nav-bar using Angular2+ Material 2 and flex-layout in angular-cli app.

(Please visit Install Angular Material and Angular CDK)

1) Install flex-layout

npm install @angular/flex-layout -save

2) Include flex-layout in your app.module.ts

import {FlexLayoutModule} from "@angular/flex-layout";

3) Import

imports: [
 BrowserModule,
 FormsModule,
 HttpModule,
 RoutingModule,
 FlexLayoutModule,
MyOwnCustomMaterialModule // Please visit the link above "Install Angular Material and Angular CDK", and check (Step 3: Import the component modules).
],

app.component.html

<mat-toolbar color="primary">

    <button mat-button routerLink="/">
    <mat-icon>home</mat-icon> 
        {{title}}</button>

    <!-- This fills the remaining space of the current row -->
    <span class="fill-remaining-space"></span>
    <div fxLayout="row" fxShow="false" fxShow.gt-sm>
        <button mat-button routerLink="/products">Products</button>
        <button mat-button routerLink="/dashboard">Dashboard</button>
    </div>
    <button mat-button [mat-menu-trigger-for]="menu" fxHide="false" fxHide.gt-sm>
     <mat-icon>menu</mat-icon>
    </button>

</mat-toolbar>
<mat-menu x-position="before" #menu="matMenu">
    <button mat-menu-item routerLink="/products">Products</button>
    <button mat-menu-item routerLink="/dashboard">Dashboard</button>
    <!--<button mat-menu-item>Help</button>-->
</mat-menu>

app.component.css

.fill-remaining-space {
   /*This fills the remaining space, by using flexbox.  
  Every toolbar row uses a flexbox row layout. */
  flex: 1 1 auto;
}

Note: to test, resize your page.

take a look at flex-layout docs

Upvotes: 55

Tomasz Chudzik
Tomasz Chudzik

Reputation: 1947

Here is my favorite way of creating a responsive Navigation Bar in Angular. If you use Angular 6, make sure you use a version 6.1+
Working example on Stackblitz: https://stackblitz.com/edit/angular-v6xwte

Example on a smaller screen: Toolbar on a small screen

Example on a larger screen: Toolbar on a large screen

Here are precise steps how to do it:

1) Install necessary packages. Type in your terminal:

npm install --save @angular/material @angular/cdk @angular/animations

npm install @angular/flex-layout --save

2) Import necessary modules in your app.module.ts

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FlexLayoutModule } from '@angular/flex-layout';
import {
  MatIconModule, MatButtonModule, MatSidenavModule, MatToolbarModule
} from '@angular/material';

Remember to add these modules to the imports array below.

3) Add Material Icons link to your index.html
The link must go before any Angular content.

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

4) In your styles.css add an Angular theme and set margins to 0%

@import "~@angular/material/prebuilt-themes/indigo-pink.css";
body{
    margin: 0%;
}

5) Add toolbar HTML code in your app.component.html

<div style="height: 100vh;"> 
<mat-toolbar color="primary">
    <div fxShow="true" fxHide.gt-sm="true">
      <button mat-icon-button (click)="sidenav.toggle()">
        <mat-icon>menu</mat-icon>
      </button>
    </div>
    <a mat-button class="companyName" routerLink="/">
      <span>Site name</span>
    </a>
    <span class="example-spacer"></span>
    <div fxShow="true" fxHide.lt-md="true">
      <a mat-button routerLink="/about-us">About us</a>
      <a mat-button routerLink="/prices">Prices</a>
      <a mat-button routerLink="/start-page">Start page</a>
      <a mat-button routerLink="/offer">Offer</a>
      <a mat-button routerLink="/contact">Contact</a>
    </div>
  </mat-toolbar>
  <mat-sidenav-container fxFlexFill class="example-container">
    <mat-sidenav color="primary" #sidenav fxLayout="column" mode="over" opened="false" fxHide.gt-sm="true">
      <div fxLayout="column">
        <a mat-button routerLink="/about-us">About us</a>
        <a mat-button routerLink="/prices">Prices</a>
        <a mat-button routerLink="/start-page">Start page</a>
        <a mat-button routerLink="/offer">Offer</a>
        <a mat-button routerLink="/contact">Contact</a>
      </div>
    </mat-sidenav>
    <mat-sidenav-content fxFlexFill>
      Awesome content
    </mat-sidenav-content>
  </mat-sidenav-container>
</div>

6) Style the toolbar in your app.component.css

.companyName{
    font-size: 150%;
}
div {
    overflow: inherit;
}
a{
    text-decoration: none;
    font-size: 110%;
    white-space: normal;
}
button{
    font-size: 110%;
    min-width: min-content;
}
.example-icon {
    padding: 0 14px;
  }

  .example-spacer {
    flex: 1 1 auto;
  }
  .mat-sidenav-content{
      font-size: 200%;
      text-align: center;
  }

Upvotes: 18

Splaktar
Splaktar

Reputation: 5894

My presentation, Create Enterprise UIs That Your Users Will Love, covers some of these patterns for Angular Material. The links to the StackBlitz examples are in the speaker notes.

Responsive Button Bar with an Overflow menu: This could be placed in or under the TopNav. https://stackblitz.com/edit/material-responsive-button-bar?file=app%2Fbutton-bar%2Fbutton-bar.component.ts

Dynamic Nested TopNav Menu: Note that this menu is not fully accessible. More work is needed to fully support a good a11y experience. https://stackblitz.com/edit/dynamic-nested-topnav-menu?file=app/app.component.ts

Dynamic Nested SideNav Menu: If you use the Transform Pattern to switch your TopNav to a SideNav on mobile, this shows how to build a dynamic SideNav menu. https://stackblitz.com/edit/dynamic-nested-sidenav-menu?file=app%2Fapp.component.html

Upvotes: 3

Cengiz
Cengiz

Reputation: 123

I have edited user2662006's answer with some fixes and code optimizations below. Note that my StackOverflow points are currently too low to even grant me the privilege to submit a comment let alone editing.

1) Install Angular Material and Angular CDK

2) Install flex-layout

npm install @angular/flex-layout -save

3) Include flex-layout in your app.module.ts

import {FlexLayoutModule} from "@angular/flex-layout";

4) Import related material and flex modules

imports: [
 ...,
 FlexLayoutModule,
 MatToolbarModule,
 MatIconModule,
 MatMenuModule,
 MatButtonModule,
],

app.component.html

<mat-toolbar color="primary">
    <button mat-button routerLink="/">
        <mat-icon>home</mat-icon> 
        {{title}}
    </button>

    <span class="fill-remaining-space"></span>

    <div fxLayout="row" fxHide fxShow.gt-sm>
        <button mat-button routerLink="/products">Products</button>
        <button mat-button routerLink="/dashboard">Dashboard</button>
    </div>
    <button mat-button [mat-menu-trigger-for]="menu" fxShow fxHide.gt-sm>
     <mat-icon>menu</mat-icon>
    </button>

</mat-toolbar>
<mat-menu x-position="before" #menu>
    <button mat-menu-item routerLink="/products">Products</button>
    <button mat-menu-item routerLink="/dashboard">Dashboard</button>
</mat-menu>

app.component.css

.fill-remaining-space {
   /*This fills the remaining space, by using flexbox.  
  Every toolbar row uses a flexbox row layout. */
  flex: 1 1 auto;
}

Notes:

Upvotes: 4

Melroy van den Berg
Melroy van den Berg

Reputation: 3156

You can build a responsive menu by using mat-toolbar, mat-sidenav and flex-layout (fxFlexFill, ...).

See Stackblitz example.

More info...

Upvotes: 2

Anup
Anup

Reputation: 618

My crude attempt to modify the answer with a toolbar with drawer implementation with new component names as of angular-material 5.0.2

To do: Need to get CSS of all header links fixed. Menu icon should be transparent.

https://responsivematerial2.stackblitz.io/

.mat-sidenav-container {
  background: rgba(0, 0, 0, 0.08);
}

.blank-grow {
  flex: 1 1 auto;
}
<mat-sidenav-container fullscreen>
  <mat-sidenav #sidenav>
    <mat-nav-list>
      <a mat-list-item>
        <mat-icon mat-list-icon>home</mat-icon>
        <span mat-line>home</span>
      </a>

      <a mat-list-item>
        <mat-icon mat-list-icon>backup</mat-icon>
        <span mat-line>Backup</span>
      </a>
    </mat-nav-list>
  </mat-sidenav>
  <mat-toolbar color="primary">
    <button mat-icon-button (click)="sidenav.open()" fxHide="false" fxHide.gt-sm>
      <mat-icon>menu</mat-icon>
    </button>
    <span> Big Header</span>
    <span class="blank-grow"></span>
    <div fxLayout="row" fxShow="false" fxShow.gt-sm>
      <a>
        <mat-icon mat-list-icon>home</mat-icon>
        <span mat-line>home</span>
      </a>

      <a>
        <mat-icon mat-list-icon>backup</mat-icon>
        <span mat-line>Backup</span>
      </a>
    </div>
  </mat-toolbar>
</mat-sidenav-container>

Upvotes: 4

Cerny
Cerny

Reputation: 305

Have a look at angular2-material project on github. Here is a list of material design components they have published so far:

https://www.npmjs.com/~angular2-material

Also, I think either md-sidenav or md-toolbar is what you are looking for.

md-sidenav - https://www.npmjs.com/package/@angular2-material/sidenav

md-toolbar - https://www.npmjs.com/package/@angular2-material/toolbar

Note: The project is still in alpha release which means there can be breaking changes in their API. Not recommended to use in production.

Upvotes: 4

Related Questions