Home > Software engineering >  Angular - Block navigation from component (without route guard)
Angular - Block navigation from component (without route guard)

Time:11-08

I'm trying to prevent navigation until the user confirms they will lose their changes, but I don't think I can use a route guard in my scenario.

Here is the check for changes:

public get hasChanged(): boolean {
    return this.changeManager.hasChanged({
        propA: this.propACtrl.value,
        propB: this.propBCtrl.value,
        // ETC, lots of other checks
    });
}
class ChangeManager {
    // bunch of properties containing original values

    public hasChanged(args: ChangeManagerArguments): boolean {
        return this.propA !== args.propA || this.propB !== args.propB // etc...
    }
}

Therefore, I don't think I can use a service, since this check is done at a specific timing, the service will not have that information (since it doesn't have access to all those properties it needs to check).

For the moment, I can handle the scenario where the user uses the browser features to leave the page (back button, home button, closing tab etc...) by doing this:

@HostListener("window:beforeunload")
public unloadHandler(): boolean {
    if (this.hasChanged) {
        return false;
    }

    return true;
}

How can I have something similar if the user navigates via a routerLink? Is there a way to achieve this with a route guard?

CodePudding user response:

First need to create PendingChangesGuard as below:

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

@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate,
            route: ActivatedRouteSnapshot, 
            state: RouterStateSnapshot,
            nextState: RouterStateSnapshot): boolean | Observable<boolean> {
       
             
    // if there are no pending changes, just allow deactivation; else confirm first
     return component.canDeactivate() ?
       true :
       confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
  }
}

Routing Path add Guard

{ path: 'path...', component: ComponentName, canDeactivate: [PendingChangesGuard] },

//Write below code in component where you want to check the change done or not?

@HostListener('window:beforeunload')
  canDeactivate(): Observable<boolean> | boolean {
    // insert logic to check if there are pending changes here;
    // returning true will navigate without confirmation
    // returning false will show a confirm dialog before navigating away
    if(this.list.length>0){   // Check whatever condition you have 
       return false;
    }
     else{
       return true;
    }
    
}
  • Related