This solution is just a work around and has its flaws. It is mentioned below.
Steps :
In the template :
-
Disable all tabs of the mat-tab-group
<mat-tab label="Tab 0" disabled>
-
Provide a click event handler on mat-tab-group.
Also set theselectedIndex
property using a variable from the component class.<mat-tab-group (click)="tabClick($event)" [selectedIndex]="selectedTabIndex">
In the Component class :
-
Declare the variable
selectedTabIndex
selectedTabIndex = 0;
-
Create a method to get the tab Index , provided the tab label.
getTabIndex(tabName: string): number { switch (tabName) { case 'Tab 0': return 0; case 'Tab 1': return 1; case 'Tab 2': return 2; default: return -1; // return -1 if clicked text is not a tab label text } }
We can get the tab-label text from a property of the click event
`clickEventName.toElement.innerText`
-
Create the method for handling the click event on mat-tab-group.
tabClick(clickEvent: any) { // Get the index of clicked tab using the above function const clickedTabIndex = this.getTabIndex(clickEvent.toElement.innerText); // if click was not on a tab label, do nothing if (clickedTabIndex === -1) { return; } // if current tab is same as clicked tab, no need to change. //Otherwise check whether editing is going on and decide if (!(this.selectedTabIndex === clickedTabIndex)) { if ( /*logic for form dirty check*/ ) { // if form is dirty, show a warning modal and don't change tab. } else { // if form is not dirty, change the tab this.selectedTabIndex = clickedTabIndex; } }
}
In my case each tab content was in separate components. So I used @ViewChild
to access them and check whether any of the form is dirty or not.
Flaws :
-
Since this method uses the text of clicked element for switching tabs, there is a chance that one of your tab may contain some element with text content same as
the heading of other tabs.So it may trigger a tab change. You can look for other properties in click event to prevent this scenario if possible.
I used following code intabClick()
method’s beginningif (!((clickEvent.toElement.className).toString().includes('mat-tab-label'))) { return; }
-
You may need to override the
css
ofdisabled
state ofmat-tab
to make it look natural
Template :
<mat-tab-group (click)="tabClick($event)" [selectedIndex]="selectedTabIndex">
<mat-tab label="Tab 0" disabled>
// Tab 0 Content
</mat-tab>
<mat-tab label="Tab 1" disabled>
// Tab 1 Content
</mat-tab>
<mat-tab label="Tab 2" disabled>
// Tab 2 Content
</mat-tab>
</mat-tab-group>