Reputation: 68
I can not open a sidenav from another component. The error is in the image at the end of this question. I would like to use this style of sidenav in my code:
https://stackblitz.com/angular/lronayrmlye?file=src%2Fapp%2Fsidenav-autosize-example.ts
but I want to be able to open the sidenav from another component,
Component containing the button: navigation.component
Component containing the sidenav: layouts.component
sidebar.service.ts
import { Injectable, EventEmitter } from '@angular/core';
import { MatSidenav, MatDrawer } from '@angular/material/sidenav';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class SidenavService {
public sideNavToggleSubject: BehaviorSubject<any> = new BehaviorSubject(null);
private drawer: MatDrawer;
constructor() {}
setDrawer(drawer: MatDrawer) {
this.drawer = drawer;
}
toggle(): void {
this.drawer.toggle();
}
}
navigation.component.html
<mat-toolbar-row>
<button type="button" class="open-sidebar" mat-button (click)="toggled()">
Toggle sidenav
</button>
</mat-toolbar-row>
navigation.component.ts
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { MediaMatcher } from '@angular/cdk/layout';
import { SidenavService } from '../services/sidenav.service';
import { MatSidenav } from '@angular/material/sidenav';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent {
constructor(private sidenavService: SidenavService) { }
toggled() {
this.sidenavService.toggle();
}
}
layouts.component.html
<div>
<div class="mat-typography">
<app-navigation></app-navigation>
<router-outlet></router-outlet>
</div>
<mat-drawer-container class="example-container colorred" autosize>
<mat-drawer #drawer class="example-sidenav" position="end" mode="side">
<p>Auto-resizing sidenav</p>
<p *ngIf="showFiller">Lorem, ipsum dolor sit amet consectetur.</p>
<button (click)="showFiller= !showFiller" mat-raised-button>
Toggle extra text
</button>
</mat-drawer>
</mat-drawer-container>
</div>
layouts.component.ts
import { Component, VERSION as ngv, ViewChild } from '@angular/core';
import { MatSidenavModule, MatDrawer } from '@angular/material/sidenav';
import { SidenavService } from 'src/app/layouts/services/sidenav.service';
@Component({
selector: 'app-layouts',
templateUrl: './layouts.component.html',
styleUrls: ['./layouts.component.scss']
})
export class LayoutsComponent {
@ViewChild('drawer') public drawer: MatDrawer;
public showFiller = false;
constructor(private sidenavService: SidenavService) { }
ngOnInit() {
this.sidenavService.setDrawer(this.drawer);
}
}
Upvotes: 3
Views: 1569
Reputation: 330
Everything is true in your code except you did not set static to the drawer in ViewChild in the layout component.
@ViewChild('drawer', { static: true }) public drawer: MatDrawer;
Upvotes: 4
Reputation: 3312
In your service, you should update your @Injectable
decorator like so:
@Injectable({
providedIn: 'root'
})
The error you are seeing basically says that the service is undefined in your component. In other words, it isn't being injected correctly. The above code is the easiest way to provide your service at the root (AppModule), so that it's available to be injected in your components.
Upvotes: 0