Open/Close sidenav from another component
I used @Input() inputSideNav: MatSideNav
in parent\ another component to pass the sideNav object as target property from child component. It works as expected. By the way, I liked the service implementation by @Eldho :)
- It is simple to plugin in your current implementation
- It is scalable to as many sideNav or other UI controls passed as reference into the component definition
- No cluttering in code and plain as it looks.
- Vote up if you get what we mean :)
Child.component.html
<app-layout-header [inputSideNav]="sideNav"></app-layout-header>
<mat-sidenav-container>
<mat-sidenav #sideNav (click)="sideNav.toggle()" mode="side">
<a routerLink="/">List Products</a>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
layout-header.component.html
<section>
<mat-toolbar>
<span (click)="inputSideNav.toggle()">Menu</span>
</mat-toolbar>
</section>
layout-header.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Component({
selector: 'app-layout-header',
templateUrl: './layout-header.component.html',
styleUrls: ['./layout-header.component.css']
})
export class LayoutHeaderComponent implements OnInit {
@Input() inputSideNav: MatSidenav;
constructor() { }
ngOnInit() {
}
}
I had the same problem using. I resolved it like this.
SidenavService
import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Injectable()
export class SidenavService {
private sidenav: MatSidenav;
public setSidenav(sidenav: MatSidenav) {
this.sidenav = sidenav;
}
public open() {
return this.sidenav.open();
}
public close() {
return this.sidenav.close();
}
public toggle(): void {
this.sidenav.toggle();
}
Your Component
constructor(
private sidenav: SidenavService) { }
toggleRightSidenav() {
this.sidenav.toggle();
}
Bind your html toggle() based on your requirement.
App component.
@ViewChild('sidenav') public sidenav: MatSidenav;
constructor(private sidenavService: SidenavService) {
}
ngAfterViewInit(): void {
this.sidenavService.setSidenav(this.sidenav);
}
App Module
providers: [YourServices , SidenavService],
Working sample with code stackblitz
Angular 9+ Update
Per this answer on SO, "Components can no longer be imported through @angular/material
. Use the individual secondary entry-points, such as @angular/material/button.
" As such, make sure to import MatSidenav
like so:
import { MatSidenav } from '@angular/material/sidenav';