Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular4 Routing: Force Navigation By Bypassing Route Guard

When my users have dirty changes on a screen, I have a route guard to prompt them to save or discard when they try to navigate away.

However, if I am logging them out due to inactivity, I want to force navigation and bypass the route guard (by discarding their changes), in order to ensure that their screen is blanked.

How can I bypass route guards?

like image 528
masonk Avatar asked May 03 '17 17:05

masonk


People also ask

Can you disable route Guard?

CanDeactivate is a TypeScript interface that needs to be implemented by a component to create a route guard. This guard will be used by the router to decide if the route can be deactivated. It can be implemented in any Angular component using the canDeactivate method of the interface.

What is the purpose of a route Guard?

This route guard is used to keep the user from navigating away from a specific route. This guard can be useful when you want to prevent a user from accidentally navigating away without saving or some other undone tasks.

What is the difference between canActivate and CanDeactivate?

CanActivateChild - Decides if children routes of a route can be activated. CanDeactivate - Decides if a route can be deactivated.

Which route Guard can be used to mediate navigation to a route?

The Angular router's navigation guards allow to grant or remove access to certain parts of the navigation. Another route guard, the CanDeactivate guard, even allows you to prevent a user from accidentally leaving a component with unsaved changes.


2 Answers

My solution was as follows:

My logout method after successfully logging out, redirects the app to the /login route:

@Injectable
export class AuthService {
  // ...
  logout () {
    // do logout
    this.router.navigate(['/login']);
  }
}

My guard is then as follows:

@Injectable
export class DiscardChangesGuard implements CanDeactivate<MyComponent> {

  canDeactivate(component: MyComponent, currentRoute: ActivatedRouteSnapshot,
                currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean> | boolean {

    if (nextState.url === '/login') {
      return true; // bypass checks if we are trying to go to /login
    }

    // perform regular checks here
  }
}
like image 160
Aakash Jain Avatar answered Oct 23 '22 18:10

Aakash Jain


Here's how you can force a bypass on a per-navigation basis. In my case I was navigating back to the account dashboard after the user submits a form with account info.

Ideally you would check for unsaved changes in the form and bypass based on that, but my forms don't have that feature yet.

form component:

this.router.navigateByUrl('/', { state: { bypassFormGuard: true } })

router guard:

@Injectable()
export class ExitFormGuard implements CanDeactivate<ComponentCanDeactivate> {

   constructor(private router: Router) {}

   canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
      if (this.router.getCurrentNavigation()?.extras?.state?.bypassFormGuard) {
         return true
      }

      // perform normal checks
   }
}

like image 7
Kenneth Avatar answered Oct 23 '22 17:10

Kenneth