I have a requirement of throwing a popup to the user when navigating to different component from the current component.
And based on the input from the user i will have to either have to allow him to navigate away or make him stay.
After a lot of googling i have found out that using a route guard which implements canDeactivate interface is the best approach to this problem.
However even after following a step-by-step process of implementing the guard, the canDeactivate() method implemented in the guard is never triggered on any of the navigations away from my component.
Here is my guard which i have implemented as a service.
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';
import { SearchProjectComponent } from 'src/app/Project/search-project/search-project.component';
@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<SearchProjectComponent> {
canDeactivate(component: SearchProjectComponent,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot) {debugger
alert('called from guard');
const url: string = state.url;
console.log('Url: ' + url);
return component.canDeactivate ? component.canDeactivate() : true;
}
}
SearchComponent is my component for which i am trying to implement the Guard. (On navigating away from this component, i want to throw a popup prompt)
Here is my AppRoutingModule
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { AuthGuard } from './shared';
import { CanDeactivateGuard } from './shared/services/can-deactivate-guard.service';
const routes: Routes = [
{ path: '', loadChildren: () => import('./layout/layout.module').then(m => m.LayoutModule), canActivate: [AuthGuard] },
{ path: 'login', loadChildren: () => import('./login/login.module').then(m => m.LoginModule) },
{ path: 'access-denied', loadChildren: () => import('./access-denied/access-denied.module').then(m => m.AccessDeniedModule) },
{ path: 'add-project', loadChildren: () => import('./Project/add-project/add-project.module').then(m => m.AddProjectModule) },
// tslint:disable-next-line:max-line-length
{ path: 'search-project', loadChildren: () => import('./Project/search-project/search-project.module').then(m => m.SearchProjectModule), canDeactivate: [CanDeactivateGuard] },
{ path: '**', redirectTo: 'access-denied' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
On navigating to any other component from searchcomponent, the canDeactivate method doesn't even get triggered.
Here is the code in my component.
canDeactivate(): Observable<boolean> | boolean {debugger
alert('called form component');
if (this.registerForm.dirty) {debugger
return false;
//return this.dialogService.confirm('Discard changes for Person?');
}
return true;
}
Can someone help me with what i need to correct? (I am just a beginner in Angular, but i feel if this issue has something to do with the loadchildren() in the routingmodule)
You're missing to implement the component.canDeactivate
inside your component, which is the only one who knows if the user can leave out or not.
So, inside your components, implements this:
canDeactivate(): boolean {
return //condition to verify;
}
For more info, look here:
https://angular.io/guide/router#candeactivate-handling-unsaved-changes