Angular 7中mat-tab的ink bar偶尔无法显示的问题求助
I’ve run into this exact nested tab rendering quirk with Angular Material before—let’s break down what’s going on and fix it:
The Issue Breakdown
- You’ve got a nested
mat-tab-groupsetup: outer tabs for "Recent"/"Upcoming", inner tabs for match types (ALL/T20/ODI/TEST) - When switching between outer tabs, the inner tab’s ink-bar doesn’t appear initially
- Toggling Dev Tools open/close makes the ink-bar pop up suddenly
- After switching inner tabs and navigating back to the "Recent" outer tab, the inner tab resets to ALL (correct
selectedIndex2value) but the ink-bar stays hidden until Dev Tools is toggled
Root Cause
This is a classic rendering timing issue. Angular Material’s ink-bar calculates its position based on the actual DOM dimensions of the tab headers. When you switch outer tabs with animationDuration="0ms", you skip the framework’s internal rendering hooks that wait for DOM changes to settle. The ink-bar tries to compute its position before the inner tab-group’s DOM is fully sized or rendered—toggling Dev Tools triggers a reflow/repaint, which forces the ink-bar to recalculate correctly.
Fixes to Implement
1. Trigger Ink-Bar Update Manually (Most Reliable)
First, fix the duplicate template reference variable (#tabGroup is used twice—give each inner tab-group a unique name):
<mat-tab-group animationDuration="0ms" [selectedIndex]="activeIndex" (selectedTabChange)="onTabChange($event)" class="detail-page recent_tabs"> <mat-tab label="Recent"> <div class="card_left detail-page"> <mat-tab-group #recentTabGroup [selectedIndex]="activeIndex2" (selectedTabChange)="onTabChange2($event)"> <mat-tab label="ALL"></mat-tab> <mat-tab label="T20"></mat-tab> <mat-tab label="ODI"></mat-tab> <mat-tab label="TEST"></mat-tab> </mat-tab-group> </div> </mat-tab> <mat-tab label="Upcoming"> <div class="card_left detail-page"> <mat-tab-group #upcomingTabGroup [selectedIndex]="activeIndex2" (selectedTabChange)="onTabChange2($event)"> <mat-tab label="ALL"></mat-tab> <mat-tab label="T20"></mat-tab> <mat-tab label="ODI"></mat-tab> <mat-tab label="TEST"></mat-tab> </mat-tab-group> </div> </mat-tab> </mat-tab-group>
Then in your component, reference both tab groups and force the ink-bar to update when the outer tab changes:
import { Component, ViewChild } from '@angular/core'; import { MatTabGroup } from '@angular/material/tabs'; @Component({ // Your component metadata here }) export class YourComponent { activeIndex = 0; activeIndex2 = 0; @ViewChild('recentTabGroup') recentTabGroup!: MatTabGroup; @ViewChild('upcomingTabGroup') upcomingTabGroup!: MatTabGroup; onTabChange(event: any) { this.activeIndex = event.index; // Push ink-bar update to the end of the event loop to ensure DOM is ready setTimeout(() => { this.getCurrentInnerTabGroup()?.updateInkBar(); }, 0); } onTabChange2(event: any) { this.activeIndex2 = event.index; } private getCurrentInnerTabGroup(): MatTabGroup | undefined { return this.activeIndex === 0 ? this.recentTabGroup : this.upcomingTabGroup; } }
2. Ditch animationDuration="0ms" (Quick Win)
Setting the animation duration to 0 skips critical rendering hooks that handle ink-bar positioning. Try changing it to animationDuration="10ms"—it’s visually instant but gives Angular Material enough time to process DOM changes properly.
3. Reinitialize Inner Tab Groups (Drastic but Effective)
If the above fixes don’t work, use *ngIf to ensure the inner tab-group is fully recreated when switching outer tabs:
<mat-tab label="Recent"> <div class="card_left detail-page" *ngIf="activeIndex === 0"> <mat-tab-group [selectedIndex]="activeIndex2" (selectedTabChange)="onTabChange2($event)"> <mat-tab label="ALL"></mat-tab> <mat-tab label="T20"></mat-tab> <mat-tab label="ODI"></mat-tab> <mat-tab label="TEST"></mat-tab> </mat-tab-group> </div> </mat-tab> <mat-tab label="Upcoming"> <div class="card_left detail-page" *ngIf="activeIndex === 1"> <mat-tab-group [selectedIndex]="activeIndex2" (selectedTabChange)="onTabChange2($event)"> <mat-tab label="ALL"></mat-tab> <mat-tab label="T20"></mat-tab> <mat-tab label="ODI"></mat-tab> <mat-tab label="TEST"></mat-tab> </mat-tab-group> </div> </mat-tab>
Why This Works
The updateInkBar() method forces Angular Material to recalculate the ink-bar’s position based on the current DOM state. The setTimeout with 0ms delay pushes this calculation to the end of the event loop, ensuring the inner tab-group’s DOM is fully rendered before the ink-bar updates.
内容的提问来源于stack exchange,提问作者VIKAS KOHLI

