angularangular7angular-router-guardsangular-route-guards

Angular's route guard is not running within app


I've added a route with a guard on it to my app-routing.module.ts file like so:

{path: 'detail/:id', component: DetailComponent, canDeactivate: [PendingChangesGuard]},

If I try to completely leave the angular application then I see my expected message pop up from the PendingChangesGuard. However, if I click on any other route within the angular application, then the route guard isn't executed. How do I make it run in that case as well?

This is what the route guard file looks like:

export interface ComponentCanDeactivate {
    canDeactivate: () => boolean;
}

@Injectable({
    providedIn: 'root'
})
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
    canDeactivate(component: ComponentCanDeactivate, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return component.canDeactivate ? true : confirm('WARNING: You have unsaved changes. Press Cancel to go back and save your changes.');
    }
}

and in the DetailComponent I did this:

@HostListener('window:beforeunload')
canDeactivate(): boolean {
    console.info("I got called");
    return !this.formGroup.dirty;
}

Solution

  • You're not actually calling component.canDeactivate in your guard. You're basically checking if it is defined (which is always true) and then returning true.

    Update to:

    export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
        canDeactivate(component: ComponentCanDeactivate, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
            return component.canDeactivate() ? true : confirm('WARNING: You have unsaved changes. Press Cancel to go back and save your changes.');
        }
    }