Lahiru Chandima
Lahiru Chandima

Reputation: 24068

How to conditionally prevent user from navigating to other tab in mat-tab-group

I have an angular component which uses an angular material tab group.

<mat-tab-group>
  <mat-tab label="First"> <app-comp1></app-comp1> </mat-tab>
  <mat-tab label="Second"> <app-comp2></app-comp2> </mat-tab>
  <mat-tab label="Third"> <app-comp3></app-comp3> </mat-tab>
</mat-tab-group>

In a certain tab, user can do some changes and save. If user did some changes and tries to navigate to another tab without saving, I want to ask the user for confirmation to discard changes before navigating to the other tab.

Is there any way to do this?

Upvotes: 5

Views: 12360

Answers (3)

Someone Else
Someone Else

Reputation: 1

You can replace Yurzui solution by using Subjects, as to use a modal instead of a window.comfirm(). This will work in Angular 17 with RxJS lib. (Hope it helps GeekyMonkey and others)

  • Create a new Subject<void>() variable.

  • Create a function for your (click) in file.html.

  • Put this.NameOfSubject.next(); in the function.

  • In NgInit, write the line from the other answer.

  • Add a ViewChild like they did but modified:

    @ViewChild('tabs', {static: true}) tabs: MatTabGroup;
    
  • In the second function (interceptTabChange()), you can call your modal window opening method, then subscribe to your subject.

  • In the subscribe method, you can do:

    MatTabGroup.prototype._handleClick.apply(this.tabs, [tab, tabHeader, idx])
    

Don't forget to create your modal in your .html file where you have your button with the (click) calling the method you created before.

Then, the code should open your custom modal window and clicking on the button where you set in the new click function, and will allow the user to change tab.

Upvotes: 0

GeekyMonkey
GeekyMonkey

Reputation: 12974

The accepted answer has stopped working for me in the latest vue version.

Another option is to set the other tabs to disabled when the active tab is in a state that is incomplete.

<mat-tab-group>
  <mat-tab label="Form">Form Here</mat-tab>
  <mat-tab label="Result" >Result Here</mat-tab>
</mat-tab-group>

Upvotes: 1

yurzui
yurzui

Reputation: 214007

If there is no solution today then i can offer you some trick based on monkey patching:

template.html

<mat-tab-group #tabs>
  ...
</mat-tab-group> 

component.ts

import { MatTabGroup, MatTabHeader, MatTab } from '@angular/material';
...
@Component({...})
export class AppComponent implement OnInit {
  @ViewChild('tabs') tabs: MatTabGroup;

  ngOnInit() {
    this.tabs._handleClick = this.interceptTabChange.bind(this);
  }

  interceptTabChange(tab: MatTab, tabHeader: MatTabHeader, idx: number) {
    const result = confirm(`Do you really want to leave the tab ${idx}?`);

    return result && MatTabGroup.prototype._handleClick.apply(this.tabs, arguments);
  }
}

Ng-run Example

Upvotes: 24

Related Questions