I use angular (latest version) and angular material.
There are 3 components:
How to open / close sidenav from another component ? (in my case, the button is in header.component).
Tried the following option (but got the error: TypeError: this.RightSidenavComponent.rightSidenav is undefined):
header.component.html
<button mat-button (click)="toggleRightSidenav()">Toggle side nav</button>
header.component.ts
import { Component } from '@angular/core'; import { RightSidenavComponent } from '../right-sidenav/right-sidenav.component'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.scss'] }) export class HeaderComponent { constructor(public RightSidenavComponent:RightSidenavComponent) { } toggleRightSidenav() { this.RightSidenavComponent.rightSidenav.toggle(); } }
sidenav.component.html
<mat-sidenav-container class="sidenav-container"> <mat-sidenav #sidenav mode="side" opened="true" class="sidenav" [fixedInViewport]="true"> Sidenav </mat-sidenav> <mat-sidenav-content> <app-header></app-header> <router-outlet></router-outlet> <app-right-sidenav #rSidenav></app-right-sidenav> </mat-sidenav-content> </mat-sidenav-container>
sidenav.component.ts
import { Component, Directive, ViewChild } from '@angular/core'; import { RightSidenavComponent } from '../right-sidenav/right-sidenav.component'; @Component({ selector: 'app-sidenav', templateUrl: './sidenav.component.html', styleUrls: ['./sidenav.component.scss'] }) export class SidenavComponent { @ViewChild('rSidenav') public rSidenav; constructor(public RightSidenavComponent: RightSidenavComponent) { this.RightSidenavComponent.rightSidenav = this.rSidenav; } }
right-sidenav.component.html
<mat-sidenav #rightSidenav mode="side" opened="true" class="rightSidenav" [fixedInViewport]="true" [fixedTopGap]="250"> Sidenav </mat-sidenav>
right-sidenav.component.ts
import { Component, Injectable } from '@angular/core'; @Component({ selector: 'app-right-sidenav', templateUrl: './right-sidenav.component.html', styleUrls: ['./right-sidenav.component.scss'] }) @Injectable() export class RightSidenavComponent { public rightSidenav: any; constructor() { } }
Non-working sample with code stackblitz
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';
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 :)
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() { } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With