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:

  1. This component was generated by using Angular Materials navigation schematics.
  2. I called my component my-menu however, you may use any other name.
  3. The sidenav will only close if we are not on a handset device, this is done using the rxjs operator withLatestFrom combined with the isHandset$ 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.