Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material - Know exactly which tab was selected

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:

View

<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.

Script

onTabChange(event: MatTabChangeEvent) {
  // ?
}

Issue

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:

  • test again for every tab condition within onTabChange to figure out which index corresponds to which tab,
  • (probably) bind a ViewChild(ren) reference to something and retrieve data (such as data- attributes) through their native DOM elements.

Both these options seem super overkill though.

Question

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.

like image 859
Jeto Avatar asked Nov 01 '18 10:11

Jeto


People also ask

What is matTabContent?

Material tabs (with matTabContent ) are rendering multiple instances of the tab body inside the same tab when switching away and back too fast.

How do you conditionally prevent users from navigating to other tab in Mat tab group?

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.

What is Mat tab in angular?

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.


2 Answers

Actually answering myself twice because I think this solution is interesting as well, and probably closest (yet) to what I'm looking for:

View

<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>

Script

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.

like image 54
Jeto Avatar answered Nov 15 '22 08:11

Jeto


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') { ... }
}
like image 26
Vilmantas Baranauskas Avatar answered Nov 15 '22 08:11

Vilmantas Baranauskas