How can I close Material SideNav by clicking on an element which has the RouterLink directive?
Here's a complete solution based off of Angular Material's schematics generated sidenav layout component. This answer improves on the previous ones by taking into consideration whether we are on a handset device or not, and making sure the sidenav only closes on a handset device.
A few points:
- This component was generated by using Angular Materials navigation schematics.
- I called my component
my-menu
however, you may use any other name. - The sidenav will only close if we are
noton a handset device, this is done using therxjs
operatorwithLatestFrom
combined with theisHandset$
stream which was generated by the schematics.
import { Component, ViewChild } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, filter, withLatestFrom } from 'rxjs/operators';
import { Router, NavigationEnd } from '@angular/router';
import { MatSidenav } from '@angular/material';
@Component({
selector: 'app-my-menu',
templateUrl: './my-menu.component.html',
styleUrls: ['./my-menu.component.css']
})
export class MyMenuComponent {
@ViewChild('drawer') drawer: MatSidenav;
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches)
);
constructor(private breakpointObserver: BreakpointObserver,
router: Router) {
router.events.pipe(
withLatestFrom(this.isHandset$),
filter(([a, b]) => b && a instanceof NavigationEnd)
).subscribe(_ => this.drawer.close());
}
}
I created a service so that the sidenav could be controlled from various components. I followed this example.
Then it's a matter of watching the router for events and closing as needed. In app.component.ts:
this.router.events.subscribe(event => {
// close sidenav on routing
this.sidenavService.close();
});
This doesn't work if you want to close the sidenav on only specific links, but the service itself would facilitate that.
You don't need to make a service for this. This is a simple solution.
<mat-sidenav-container [hasBackdrop]="true">
<mat-sidenav #sidenav mode="side" class="sideNavigation">
<mat-nav-list>
<a mat-list-item routerLink="" (click)="sidenav.close()"> bar</a>
<a mat-list-item routerLink="/bar" (click)="sidenav.close()">foo</a>
<a mat-list-item routerLink="/foo" (click)="sidenav.close()">whatever</a>
<a mat-list-item routerLink="/something1" (click)="sidenav.close()">SomePage</a>
<a mat-list-item routerLink="/something2" (click)="sidenav.close()">Some Page</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="accent">
<mat-icon (click)="sidenav.toggle()">menu</mat-icon>
<div class="divider"></div>
<img class="img" src="../assets/img/logo.png" alt="logo" (click)="goHome()" />
</mat-toolbar>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
All you do is add (click)="sidenav.close()"
along with the routerLink="/whatever/path/here"
works. This will close the sidenav
on directing to a page.