Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switch md-sidenav mode (Angular Material 2)

I'm interested in changing the md-sidenav - from Angular Material 2 - mode from side (for desktops) to over (mobile). Is there a way to change it programmatically? Thanks

like image 600
Michele Sapignoli Avatar asked Feb 23 '17 14:02

Michele Sapignoli


People also ask

How do I use Sidenav in angular materials?

To set up a sidenav we use three components: <mat-sidenav-container> which acts as a structural container for our content and sidenav, <mat-sidenav-content> which represents the main content, and <mat-sidenav> which represents the added side content.

How do I know if my Sidenav mat is open?

From the docs: A mat-sidenav can be opened or closed using the open(), close() and toggle() methods. Each of these methods returns a Promise that will be resolved with true when the sidenav finishes opening or false when it finishes closing.


3 Answers

Building on Steve G's solution you could update app.component.html

<md-sidenav [mode]="isLargeScreen() ? 'side' : 'over'" [opened]="isLargeScreen()"></md-sidenav>

And then in app.component.ts

isLargeScreen() {
  const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  if (width > 720) {
      return true;
  } else {
      return false;
  }
}

This gives you a sidebar on desktop opened by default, and on mobile it overlays but is hidden by default!

like image 50
Kim T Avatar answered Oct 16 '22 18:10

Kim T


I found the solution by ObservableMedia.

Component:

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

@Component({
  moduleId: module.id,
  selector: 'app-sidebar',
  templateUrl: './sidebar.component.html',
  styleUrls: ['./sidebar.component.scss'],
  encapsulation: ViewEncapsulation.None,
})
export class SidebarComponent implements OnInit {

  constructor(public media:ObservableMedia ) {
  }

  ngOnInit(): void {
  }

}

template:

<md-sidenav-container>
    <md-sidenav #sidenav  mode="{{media.isActive('gt-sm') ? 'side' : 'over'}}" align="begin" class="md-whiteframe-4dp" opened >
      <md-nav-list>
        ...
      </md-nav-list>
    </md-sidenav>

</md-sidenav-container>
like image 36
Dasma Avatar answered Oct 16 '22 16:10

Dasma


Sure! You could do your screen width test (or browser detection, blech) in your component on initialization and store the result in a variable as a string.

Using width detection as an example, you might do something like this:

Partial app.component.ts

import { Component, ElementRef, ViewChild, OnInit } from '@angular/core';

export class AppComponent implements OnInit {
  @ViewChild('wrapper') 
  private wrapperElement: ElementRef;

  private menuMode; // Where we'll store the resulting menu mode

  ngOnInit() {
    // Do your simple test on the container, for example
    if (this.wrapperElement.nativeElement.offsetWidth <= 720) {
        this.menuMode = "over";
    } else {
        this.menuMode = "side";
    }
  }
}

And bind the variable to the sidenav in the template.

Partial app.component.html

<div #wrapper>
    <md-sidenav-container>
        <md-sidenav #sidenav [mode]="menuMode"></md-sidenav>
        ...
</div>

The bulk of that work is just determining how you want to perform the test.

You could also just test window instead of a wrapper, but I prefer testing a wrapper.

Notes:

  1. This is untested code.
  2. This will fire only on initialization of the component, if you also want to handle the case where the user resizes their browser and the menu mode changes, you'll need to do something a little more fancy using HostListener @HostListener("window:resize", ["$event"]), but that's outside of the scope of your original question.
like image 1
Steve Gomez Avatar answered Oct 16 '22 17:10

Steve Gomez