Implementing custom confirmation modal for canDeactivate
Nikhil Dhawan
Posted on June 23, 2021
Hi all, in this article, we will discuss what canDeactivate means and how to have a custom confirmation modal implemented based on our app theme.
canDeactivate Router Guard
In Angular we get in build support for the routes we define to have implementation for canDeactivate guard which is how we can restrict the user from moving away from the view when some work is in progress on the current view. Example User is making an edit on his profile page and didn't click on the save button so at that time if we have implemented the router guard for canDeactivate, the user will be asked for the confirmation.
A typical implementation for the canDeactivate looks like
canDeactivate(
component: Component,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
}
So the thing to take care of here is that what does this function expects to be returned. We can have the exact value of true and false or even an observable or promise which will give true or false or UrlTree or direct UrlTree. So whenever you are implementing this make sure to have the return type which matches the above.
Working Example
So let us see how we can practically implement this guard. We can start with creating the guard service file, you can use Angular CLI to create one by the command
ng g guard custom-guard
Here we will get the options to implement different router guards available
But here as we are discussing canDeactivate, we will select that and proceed.
So here is the use case, we have 2 components and we will have router guard implemented on comp1 and when the user is trying to move from comp1 to comp2.
Complete example can be seen on Stackblitz
For code used in comp1, comp2 and confirm-modal it can be referred, here I will talk about code used in route guard.
typescript
export class ConfirmguardGuard implements CanDeactivate<Comp1Component> {
canDeactivate(
component: Comp1Component,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
console.log('deactivate');
let subject = new Subject<boolean>();
component.openDialog();
subject = component.subject;
return subject.asObservable();
}
}
and in routes array object use as
typescript
const routes: Routes = [
{
path: 'comp1',
canDeactivate: [ConfirmguardGuard],
component: Comp1Component,
},
{ path: 'comp2', component: Comp2Component },
{ path: '', redirectTo: 'comp1', pathMatch: 'full' },
];
This is the simple code that will help us to have our working router guard. We are converting the subject we had for handling the confirm modal user interactions to the observable which is what this guard expects as the return. Here I haven't added any business logic which can be based upon the variables of the component. Now when you click on Comp2, you will be asked for the confirmation and if you click on OK, you will be navigated away and on Cancel, you will remain on the same view. Here the observable which is returned by canDeactivate will only take the first value it gets.
Hope this small example helped you in understanding something new about canDeactivate, what is it used, and how to use it in Angular.
If you liked it please share it with your friends or if any suggestions reach me out on Twitter or comment below.
Till next time Happy Learning!
Posted on June 23, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.