Route Guards  in Angular

Route Guards in Angular

Guards are nothing but some code/logic executed before the route is even loaded or when the user tries to exit from the route. They're generally known as routing guards.

Open on Github - https://github.com/niharika293/Angular-rout-guard-poc

Objectives :

  • Prevents the users from accessing the parts of our app without authorization.

  • Secure the route paths.

  • Resolve to true/false based upon some custom logic.

  • Any number of guards is possible in our app.

Basic Use Case / Example -

  • Consider an e-commerce app, e.g. Amazon; Amazon restricts the users from viewing the orders page/feature until & unless he's authorized/logged in.

Types of Interfaces available -

  • canActivate: checks to see if the user can visit a route.

  • canActivateChild: checks to see if the user can visit a route's children.

  • canDeactivate: checks to see if the user can exit a route.

  • canLoad: checks before loading a feature module/assets. Best use case -> to check whether the lazy loaded modules can be loaded or not.

  • resolve: pre-fetches the route data.

Implementation -

ng g guard auth - When you hit the command, it'll ask which interfaces you want to implement. I've selected all to demo my example over here.

  1. Check auth-guard.ts file, looks like this, By default, the interfaces return true which means we can access the routes, else not possible.

  2. Let's use these! Open the app-routing.ts file & add the below code, and set up basic components & routes.

    Now, let's give the "canActivate" guard on the orders component, As I want only those users to access this route, who are authenticated with the system.

  3. Modify the routing file, since an array is passed, so more than 1 guard can also be checked for a route -

    - Add logic to the guard, Note - We're returning true only if the flag is true.

    - Now, check the browser! The route responds to the guard.

- canActivateChild: similar to canActivate, but difference -> it runs before each child route is activated.

- Use case - We want all the authorized users to access the orders page, but not the children pages like edit, add etc. So, on a parental level, we can have the "AuthGuard" & also the "AuthChildrenGuard" for child routes.

  • Now, in the POC, I've disabled the child guard, hence the user won't be able to access the child but the parent!

  • When we type orders/edit, it gets erased from the browser & the page will be blank.

- canLoad: Since, in a real-time app, we have multiple modules. To restrict a module from getting loaded, we use the "canLoad" guard. The "canActivate" guard prevents the users from accessing the unauthorized route, but it can't stop the modules from getting loaded, to overcome this condition we use "canLoad".

  • To implement this, the module should be lazy-loaded. By default, the modules are "eagerly-loaded" which means that all the modules are loaded all at once. But, in lazy loading, only those modules are loaded whose paths are specified.

  • For eg. Load the "Admin" module only if the route path consists of "admin". To lazy-load, we use "loadChildren" in the route definition.

  • How to perform Lazy loading? It's very simple. Use the following command, it'll automatically generate a lazy-loaded route.

    • ng g module <module-name> --route <route-name> --module <in which module it should go?>

    • In my case, I'm creating a profile module within our app module, & I'm going to protect it with profile-check-guard.

    • Also, check the network tab, the profile module gets loaded separately.

    • Now, we've changed the code & we're returning false from the profile-check guard & we've used this guard on our route.

    • Going back to the browser, we see that profile module won't be loaded anymore & we'll see a blank page.

- canDeactivate : to check if the user can exit a particular route. Use cases -

  • While filling in any payment info, and filling in login credentials, if the user by chance clicks on the refresh/back button, then we may prompt him an alert window whether he wants to exit from the page or not.

  • Let's make a login component & invoke the deactivate guard. If the user tries to navigate away from the page, he should be able to see a dialog window.

  • It acts upon a component, hence we need to pass the component name, It also has the instance of activatedRouteSnapshot, current route, and next route. These details can be used to access the query parameters/route parameters etc.

  • Based on the flag from the login component, we'll activate/deactivate our guard. For now, we're returning false.

  • Since our flag is false, we can navigate away from the page. Let's change it to true.

  • We've added a link on the login page to test our functionality.

- resolve : It's used when we want to fetch/send some data to the route even before it's activated.

  • Diff. B/w ngOnInit & resolve => ngOnInit will work only when the activatedRoute is equal to the current route, which means when we're currently on the route, whereas resolve works even before the route is activated.

  • Make a guard with the interface resolve :

  • Now, in our routing file, we're gonna use this & see it in action!

  • Now, go to the component & collect the route values from there.

    Thank you so much for popping in here! That's all folks! For any Query / Suggestion/feedback, connect with me over LinkedIn. :)