Search code examples
angularangular-materialangular-material2angular-flex-layout

Angular Material 2 - Responsive Toolbar


Using Angular 4 I am trying to have a toolbar on the top of the page that has the following behaviour:

Big Screens

Show the "Main"-Logo/Link on the left, the other top-nav links on the right.

Small screens

Show the "Main"-Logo Link centered and a menu button on the left for showing the sidenav (containing the links that were visible on the right if the screen is big).

Note:

The sidenav should not go over the toolbar if visible.

Note 2:

The centering of the "Main"-Logo/Link should be centered regarding the overall screen width. It should not be pushed to the right by the menu button.

What I have

<div fxLayout="column" fxFlex>
  <md-toolbar color="primary">
    <button md-icon-button (click)="sidenav.toggle()" fxHide="false" fxHide.gt-sm>
      <md-icon>menu</md-icon>
    </button>
    <button md-button routerLink="/">
      <md-icon>code</md-icon>
      <span>{{title}}</span>
    </button>
    <div fxFlex fxShow="false" fxShow.gt-sm></div>
    <div fxLayout="row" fxShow="false" fxShow.gt-sm>
      <button md-button routerLink="/about">About</button>
      <button md-button routerLink="/legal">Legal Notice</button>
    </div>
  </md-toolbar>
  <md-sidenav-container fxFlex>
    <md-sidenav #sidenav fxHide="false" fxHide.gt-sm>
      <md-nav-list>
        <a md-list-item href="">Main</a>
        <a md-list-item href="/about">About</a>
        <a md-list-item href="/legal">Legal Notice</a>
      </md-nav-list>
    </md-sidenav>
  </md-sidenav-container>
</div>

Where I struggle

  • I do not know how to center the "Main"-Logo/Link correctly
  • If I show the menu in a small screen and switch back the layout to a bigger screen, the menu does not hide

Any help would be greatly appreciated, so thank you already!


Solution

  • Answer to your First Question:

    Create a css class say fill-space and use that to center the logo:

    .fill-space {
        flex: 1 1 auto;
    }
    

    ... and in your template:

    <span fxFlex fxHide="false" fxHide.gt-sm class="fill-space"></span>
    <button md-button routerLink="/">
      <md-icon>code</md-icon>
      <span>{{title}}</span>
    </button>
    <span class="fill-space"></span>  
    

    Answer to your Second Question:

    You will have to close() the sidenav manually on screen resize. You can detect that using @HostListener('window:resize', ['$event']):

    In your typescript, do the following changes:

    // Import the following in your ts file
    import { ViewChild, HostListener } from '@angular/core';
    import { MdSidenav } from '@angular/material';
    
    // Add the following in your component class to get sidenav
    @ViewChild('sidenav') sidenav: MdSidenav;
    
    // Add the method to detect screen-resize
    @HostListener('window:resize', ['$event'])
    onResize(event) {
        if(this.sidenav !== undefined){
            this.sidenav.close();
        } 
    }
    

    Link to working demo.