In my Ionic 5 application I have the following navigation path.
PageHome -> PageA -> PageB
I have implemented CanDeactivate guard for PageA.
export class LeavePageGuard implements CanDeactivate<isDeactivatable>{
canDeactivate(
component: isDeactivatable
): Observable<boolean> | Promise<boolean> | boolean {
return component.canPageLeave();
}
}
When user edit something and press back button before saving I am raising a popup to confirm if user wants to leave.
async canPageLeave() {
if (this.byPassNav) {
this.byPassNav = false;
return true;
}
if (JSON.stringify(this.dataOld) != JSON.stringify(this.data)) {
const alert = await this.alertCtrl.create({
header: 'Unsaved Chnages',
message: 'Do you want to leave?',
buttons: [
{
text: 'No',
role: 'cancel',
handler: () => { }
},
{
text: 'Yes'),
role: 'goBack',
handler: () => { }
}
]
});
await alert.present();
let data = await alert.onDidDismiss();
if (data.role == 'goBack') {
return true;
} else {
return false;
}
} else {
return true;
}
}
To move forward to PageB
I am using a boolean
byPassNav
. I am setting this value to TRUE before moving forward and the method canPageLeave
is returning TRUE
.
The forward navigation is not working in one scenario except the following.
on PageA change some data and click on back button -> Confirmation pop up will open -> Select No -> Confirmation pop up will close and the same page remains open. Select button to move forward to PageB.
This will move the navigation to pageB
but also will make the page as Root Page and remove all route history. I can't go back from PageB
after this flow.
Edit: Adding the code for isDeactivatable
export interface isDeactivatable {
canPageLeave: () => Observable<boolean> | Promise<boolean> | boolean;
}
Seems like you just want to execute the
canDeactivate
guard when navigating back, but not when navigating forward.If that's the case, please take a look at this working Stackblitz demo:
You could avoid using the
byPassNav
(so that you don't need to update its value manually) and slightly update your guard in the following way:Please notice that the only change is that the
canLeave()
method will now get the url of the next page that the user is trying to navigate to.With that small change, you can use the url of the next page to decide if the user should see the alert prompt or not:
There's also another "alternative" approach that involves getting the navigation direction from the
NavController
.This approach is more like a workaround because the navigation direction is actually a private property from the
NavigationController
, but we can still access it if we want:This approach may sound simpler since you don't need to check the next url manually, but keep in mind that the Ionic team may remove it in the future without any notice (since it's a private property) so it may be better to just use the
nextUrl
like explained above.