So I might have missed something obvious in the docs, but I'm simply looking for an easy way to find which tab has been selected in the following scenario:
<mat-tab-group (selectedTabChange)="onTabChange($event)">
<mat-tab *ngIf="true" label="Label1">Content 1</mat-tab>
<mat-tab *ngIf="false" label="Label2">Content 2</mat-tab>
<mat-tab *ngIf="true" label="Label3">Content 3</mat-tab>
</mat-tab-group>
Obviously, the conditions are dynamic in my actual code. This is just for the sample.
onTabChange(event: MatTabChangeEvent) {
// ?
}
In the above script, event.index
will return 0 if I click the first tab, and 1 if I click the third tab, because the second one isn't displayed due to *ngIf
.
This does make sense to me, however it's making it really hard to know which tab was actually clicked depending on which ones were displayed to begin with.
I could either:
onTabChange
to figure out which index corresponds to which tab,ViewChild(ren)
reference to something and retrieve data (such as data-
attributes) through their native DOM elements.Both these options seem super overkill though.
In the above code, what would be the appropriate way to know that, say, the tab labelled Label3
was clicked, without testing for the label itself (which would obviously be horrendous)?
Simple Stackblitz if that can help.
Material tabs (with matTabContent ) are rendering multiple instances of the tab body inside the same tab when switching away and back too fast.
The solution 🕶 First, we need to add a click listener on the mat-tab-group and disable all tabs because if tabs are not disabled then the user will be able to navigate on them and we want to navigate on tabs conditionally not manually.
Tabs and navigation While <mat-tab-group> is used to switch between views within a single route, <nav mat-tab-nav-bar> provides a tab-like UI for navigating between routes.
Actually answering myself twice because I think this solution is interesting as well, and probably closest (yet) to what I'm looking for:
<mat-tab-group (selectedTabChange)="onTabChange($event)">
<mat-tab *ngIf="true" label="tab1">
<ng-template mat-tab-label>Label 1</ng-template>
Content 1
</mat-tab>
<mat-tab *ngIf="false" label="tab2">
<ng-template mat-tab-label>Label 2</ng-template>
Content 2
</mat-tab>
<mat-tab *ngIf="true" label="tab3">
<ng-template mat-tab-label>Label 3</ng-template>
Content 3
</mat-tab>
</mat-tab-group>
onTabChange(event: MatTabChangeEvent) {
const tabName = event.tab.textLabel;
// ...
}
Basically, this uses the other way to add a (title) text label to the tab, using <ng-template>
, which seems to take precedence over the label
attribute.
This latter attribute can therefore be used to store the "programmatic" name of the tab (as opposed to its public text) and is easily retrieved on script side.
Use aria-labelledby
attribute to identify tab without resorting to human-readable text labels.
<mat-tab aria-labelledby="tab-x">
<span *matTabLabel id="tab-x" i18n>Tab X</span>
</mat-tab>
In the code:
onTabChange(event: MatTabChangeEvent) {
const tabId = event.tab.ariaLabelledby;
if (tabId === 'tab-x') { ... }
}
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