_Feature request_
Version: Angular Material 2.0.0-alpha.7 wax-umpire
I'd like to have an option where the sidenav can be responsive automatically, by having a breakpoint where the sidenav is shown by default when the width is higher than X.
This was already implemented in Angular Material (1) as the md-is-locked-open
: https://material.angularjs.org/latest/api/directive/mdSidenav
Is there any plan to have this? I could submit a PR if this is wanted.
We definitely plan to do this- so far we haven't yet dove into all of the responsive behaviors for various components.
It would be great if it worked like the left sidebar in the Firebase console.
Is this doable for now? I really like the menu being locked open like Alex stated. Just added this to app.component.ts till this is supported. I'm new to Angular in general.
` @ViewChild("start") private start: MdSidenav;
constructor(private _ngZone: NgZone) { }
ngOnInit() {
//Total hack
window.onresize = (e) => {
this.checkMenu();
};
this.checkMenu();
}
checkMenu() {
this._ngZone.run(() => {
var w = window.innerWidth;
if (w > 768) {
this.start.open();
} else {
this.start.close();
}
});
}`
I did it in the FRP + Redux way (but of course you can ommit the Redux stuff). In case you wanna check it out: https://github.com/alexjoverm/Footle/blob/master/client/src/app/containers/sidenav/sidenav.component.ts
sikemullivan, that totally works, have you noticed any compatibility issues?
This seems to work too:
import { Component, ViewChild, OnInit, HostListener } from '@angular/core';
import { MdSidenav } from "@angular/material";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
@ViewChild('sidenav') sidenav: MdSidenav;
constructor(
) { }
ngOnInit() {
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < 500) {
this.sidenav.close();
}
if (event.target.innerWidth > 500) {
this.sidenav.open();
}
}
}
Another idea
import { Component, ViewChild, OnInit, HostListener } from '@angular/core';
import { MdSidenav } from "@angular/material";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
@ViewChild('sidenav') sidenav: MdSidenav;
navMode = 'side';
constructor(
) { }
ngOnInit() {
if (window.innerWidth < 768) {
this.navMode = 'over';
}
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < 768) {
this.navMode = 'over';
this.sidenav.close();
}
if (event.target.innerWidth > 768) {
this.navMode = 'side';
this.sidenav.open();
}
}
}
HTML
<md-sidenav-container class="wrapper">
<md-sidenav #sidenav mode="{{navMode}}" opened="true" class="app-sidenav">
<app-sidebar></app-sidebar></div>
</md-sidenav>
<div class='main-container'>
<app-navbar></app-navbar>
<router-outlet></router-outlet>
</div>
</md-sidenav-container>
That's perfect, thanks!!
However I was wondering if there any solution for "sidenav collapse to show icons".
Here's another way, with latest Renderer2
module:
import { Component } from '@angular/core';
import { ViewChild, Renderer2 } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
@ViewChild('sidenav') m_sidenav;
constructor(private renderer: Renderer2){
this.checkWindowWidth();
renderer.listen(window, 'resize', (event) => {
this.checkWindowWidth();
});
}
private checkWindowWidth() : void {
if(window.innerWidth > 768){
this.m_sidenav.close();
}else{
this.m_sidenav.open();
}
}
}
Here are 2 ways to make mdsidenav responsive automatically.
<md-sidenav #xxxMenu (window:resize)="$event.target.innerWidth<769?xxxMenu.close():xxxMenu.open()">
In your component,
ngOnInit():void {
this.isMobileView = (this.media.isActive('xs') || this.media.isActive('sm'));
this.subscriptionMedia = this.media.subscribe((change:MediaChange) => {
this.isMobileView = (change.mqAlias === 'xs' || change.mqAlias === 'sm');
});
In your component, add a responsive handler for link click:
onLinkClick():void {
if (this.isMobileView) {
this.menuSidenav.close();
}
}
The onLinkClick() handler needs to added to each of the menu links in your template.
It will close the menu after clicking a link, but not when the menu should stay open.
In your template, bind the md-sidenav's "mode", "opened", and "disableClose" attributes to your component's responsive boolean.
<md-sidenav #xxxMenu mode="{{isMobileView?'over':'side'}}" opened="{{!isMobileView}}" disableClose="{{!isMobileView}}">
Now, based on your responsive breakpoint...
Very nice answer, (the one about FlexLayoutModule). But FlexLayoutModule docs are as clear as mud. So could you please be a bit more specific here:
what types are:
@Denis-Frolov
They have a complete API doc with an example and the right types here: https://github.com/angular/flex-layout/wiki/ObservableMedia
@jawadst
Oh thanks, I did not see that one.
Most helpful comment
Here are 2 ways to make mdsidenav responsive automatically.
In your component,
In your component, add a responsive handler for link click:
The onLinkClick() handler needs to added to each of the menu links in your template.
It will close the menu after clicking a link, but not when the menu should stay open.
In your template, bind the md-sidenav's "mode", "opened", and "disableClose" attributes to your component's responsive boolean.
Now, based on your responsive breakpoint...