I recently upgraded my project to Angular 15.1 and noticed a new problem.
On a page I have a mat-tab-nav which opene subpages via routing:
<nav mat-tab-nav-bar color="primary">
<a mat-tab-link *ngFor="let link of navLinks" [routerLink]="link.link" routerLinkActive #rla="routerLinkActive" [active]="rla.isActive">{{link.label}}< /a>
</nav>
<router-outlet></router-outlet>
After the update everything works fine but in the console I see the error "A mat-tab-nav-panel must be specified via [tabPanel]."
Looking at the Angular code (line 385) https://github.com/angular/components/blob/main/src/material/tabs/tab-nav-bar/tab-nav-bar.ts I see the code:
override ngAfterViewInit() {
if (!this.tabPanel && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw new Error('A mat-tab-nav-panel must be specified via [tabPanel].');
}
super.ngAfterViewInit();
}
From the documentation (https://material.angular.io/components/tabs/api tabPanel) it looks like the tabPanel may be null:
tabPanel: associated tab panel controlled by the nav bar. If not provided, then the nav bar follows the ARIA link / navigation landmark pattern. If provided, it follows the ARIA tabs design pattern.
I fixed it by adding a useless mat-tab-nav-panel to my code:
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
<a mat-tab-link *ngFor="let link of navLinks" [routerLink]="link.link" routerLinkActive #rla="routerLinkActive" [active]="rla.isActive">{{link.label}}< /a>
</nav>
<mat-tab-nav-panel #tabPanel></mat-tab-nav-panel>
<router-outlet></router-outlet>
Is this the correct way? It seems to me a bug of the Angular component. What do you think?
In my Opinion you have to wrap the Router Outlet in an <mat-tab-nav-panel>
:
<nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel">
<a mat-tab-link *ngFor="let link of navLinks" [routerLink]="link.link" routerLinkActive #rla="routerLinkActive" [active]="rla.isActive">{{link.label}}< /a>
</nav>
<mat-tab-nav-panel #tabPanel>
<router-outlet></router-outlet>
</mat-tab-nav-panel>
The Documentaton states
"The corresponding <router-outlet>
must be wrapped in an <mat-tab-nav-panel>
component and should typically be placed relatively close to the mat-tab-nav-bar (see Accessibility)."
see Angular Material Tabs: Tabs and navigation
Although the code example from Angular Team is currently missing the Router-Outlet.