Reputation: 161
I have this interface that i'm using to prevent the user to leave page
export interface ComponentCanDeactivate {
canDeactivate: () => boolean;
}
@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean {
return component.canDeactivate() ?
//code : //more code
}
}
In one of my component i have the following code
export class DashboardComponent implements ComponentCanDeactivate{
@HostListener('window:beforeunload')
canDeactivate(): boolean {
return !this.isDirty;
}
My problem is that my component -> (component: ComponentCanDeactivate) from PendingChangesGuard is always null so i get an error saying
Cannot call canDeactivate() of null
I also have this setup in my routing
path: 'dashboard',
canDeactivate: [PendingChangesGuard],
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
Can someone tell me what am i doing wrong?
Upvotes: 7
Views: 6248
Reputation: 161
The issue was caused by lazy loading
Instead of having this in your app routing:
path: 'dashboard',
canDeactivate: [PendingChangesGuard], <-- causing issue
loadChildren: './views/dashboard/dashboard.module#DashboardModule'
You need to remove the canDeactive from the app routing and move it to the module routing.
const routes: Routes = [
{
path: '',
component: DashboardComponent,
canDeactivate: [ PendingChangesGuard ]
}
Upvotes: 9
Reputation: 525
I implement like this
Deactive-guard-service.ts
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable()
export class DeactivateGuardService implements CanDeactivate<CanComponentDeactivate>{
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
Component.ts
checkSave(): Promise<boolean> {
var prom = new Promise<boolean>((resolve, reject) => {
//check saved change
if(saved) resolve(true);
else reject(false);
});
return prom;
}
canDeactivate(): Promise<boolean> {
return this.checkSave().catch(function () {
return false;
});
}
Upvotes: 0
Reputation: 1324
In your PendingChangesGuard, try to inject the component itself, not the interface:
export class PendingChangesGuard implements CanDeactivate<DashboardComponent> {
constructor() {}
canDeactivate(component: DashboardComponent): boolean {
...
}
You cannot inject an interface using Angular DI as interfaces are just Typescript constructs and do not exist in Javascript code produced with the compilation process.
For more information, have a look at this SO question.
Upvotes: 0