Reputation: 139
For my web application I dynamically create tabs with *ngFor and each tab includes a sidenav-container with the sidenav and content. For each tab it should be possible to show and toggle the sidebar.
I have these components:
I also do have a service to handle toggling the sidebar.
app.component.html
<mat-tab-group class="content-container" mat-align-tabs="center">
<mat-tab *ngFor="let tab of tabs" [label]="tab.name" >
<mat-sidenav-container>
<mat-sidenav #sidenav position="start" mode="side">
<app-header></app-header>
<app-sidenav></app-sidenav>
</mat-sidenav>
<mat-sidenav-content >
<app-content></app-content>
</mat-sidenav-content>
</mat-sidenav-container>
</mat-tab>
app.component.ts
...
@ViewChild('sidenav', { static: false }) sidenav: MatSidenav
ngOnInit() {
this.sidenavService.sidenavToggleSubject.subscribe(()=> {
this.sidenav.toggle()
})
}
...
header.html
<mat-toolbar color="primary">
<button mat-icon-button class="toolbar-menu-icon" (click)="toggleSidenav()">
<mat-icon class="toolbar-menu-icon">menu</mat-icon>
</button>
</mat-toolbar>
header.ts
public toggleSidenav(){
this.sidenav.toggle()
}
sidenav.service.ts
...
public sidenavToggleSubject: BehaviorSubject<any> = new BehaviorSubject(null)
public toggle() {
return this.sidenavToggleSubject.next(null)
}
...
Problem: The sidebar does only exist for the FIRST tab. Having the first tab activated, toggling the sidebar just works as expected. But when I change to another tab and I toggle the sidebar, the sidebar of the first tab is toggled.
Example: When the sidebar of Tab1 is opened and I change to Tab 2 which does not show a sidebar and I click the icon to toggle the sidebar, the sidebar of Tab1 is closed, instead of opening a sidebar for Tab2.
For me it seems as there would be only one instance of the sidebar (which is ok, because I later want to dynamically set the content of the sidebar depending on the chosen tab), but why is it only shown on the first tab?
Upvotes: 0
Views: 437
Reputation: 3236
You are generating your tabs via an *ngFor
, so all your sidenav are generated. Angular material only "shows" one or the other, but they all exist. So your @ViewChild
in your component only gets the first #sidenav
it sees.
So what you would have to do is an @ViewChildren
to get the list of #sidenav
, so when you receive a toggle event, you check which tab is active, and toggle the this.sidenav[activeTabIndex]
instead.
@ViewChildren('sidenav', { static: false }) sidenavs: QueryList<MatSidenav>;
activeTabIndex: number = 0;
ngOnInit() {
this.sidenavService.sidenavToggleSubject.subscribe(()=> {
this.sidenavs.get(activeTabIndex).toggle();
})
}
onTabChange(newIndex: number) {
this.activeTabIndex = newIndex;
}
Upvotes: 0