5
votes

Can I make my mat-sidenav responsive using opened property or open() method and flex-layout responsive api? Like <mat-sidenav #sidenav mode="side" opened="true" [fxFlex.xs]="sidenav.close()">

3

3 Answers

10
votes

You could consider using @angular/flex-alyout ObservableMedia to watch for media/breakpoint changes and update the mode or other properties accordingly depending on the active media level. This done by subscribing to an injected ObservableMedia service instance and checking the active media level. You can then bind opened and mode properties of <md-sidenav> via one way [] binding to your class properties. This logic can be put into services and/or attribute directives if needed.

Using/updating the properties instead of applying CSS changes will ensure that the proper animations occur.

TS:

import { Component } from '@angular/core';
import { MediaChange, ObservableMedia } from "@angular/flex-layout";

@Component({ ... })
export class AppComponent  {
  mode: string = 'side';
  opened: boolean = true;

  constructor(private media: ObservableMedia) {
    this.media.subscribe((mediaChange: MediaChange) => {
      this.mode = this.getMode(mediaChange);
      // this.opened = this.getOpened(mediaChange);
    });
  }

  private getMode(mediaChange: MediaChange): string {
    // set mode based on a breakpoint
    if (this.media.isActive('gt-sm')) {
      return 'side';
    } else {
      return 'over';
    }
  }

  // open/close as needed
  private getOpened(mediaChange: MediaChange): string { }
}

HTML:

<md-sidenav-container class="example-container">
  <md-sidenav #sidenav class="example-sidenav" [opened]="opened" [mode]="mode">
    Jolly good!
  </md-sidenav>

  <div class="example-sidenav-content">
    <p>Sidenav content</p>

    <button type="button" md-button (click)="sidenav.open()">
      Open sidenav
    </button>
  </div>

</md-sidenav-container>
0
votes

One way would be to handle responsiveness in the css using flex, by giving your mat-sidenav a class depending on whether its opened or closed.

<mat-sidenav [ngClass]="sidenav.opened ? 'sideOpened' : 'sideClosed'"> 

.css

    .sideOpened {
    // Handle Responsiveness
    }
    .sideClosed {
    // Handle Responsiveness
    }
0
votes

The answer from @AlexanderStaroselsky is great but outdated/deprecated for newer versions.

As he said if you use flex-layout you can use MediaQueries from responsive API:

TS:

import { Component } from '@angular/core';
import { MediaChange, MediaObserver } from '@angular/flex-layout';

@Component({
    selector: 'app-component',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent  {
  sidenavMode: string = 'side';

  constructor(private media: ObservableMedia) {
    this.media.asObservable().subscribe((mediaChange: MediaChange[]) => {
         this.sidenavMode = this.getMode(mediaChange);
    });
  }

  private getMode(mediaChange: MediaChange[]): string {
     return this.media.isActive('gt-sm') ? 'side' : 'over';
  }

}

HTML:

<mat-drawer-container hasBackdrop="false">
    <mat-drawer [mode]="sidenavMode">
        Sidenav
    </mat-drawer>
    <div>
        Hello world !
    </div>
</mat-drawer-container>

In this example when the screen width is lower than 960px the mode will be over.