Overview Of Guards In Angular

Guards in Angular are nothing but the functionality, logic, and code which are executed before the route is loaded or the ones leaving the route.

Different types of guards,

  1. CanActivate guard (e.g. it checks route access).
  2. CanActivateChild guard (checks child route access).
  3. CanDeactivate guard (prompt for unsaved changes).
  4. Resolve guard (pre-fetching route data).
  5. CanLoad guard (check before loading feature module assets).

CanActivate Guard

  1. Create a new service say AuthenticationGuard.service.ts as below. If the AuthenticationGuard returns false then the user is not able to navigate to Home route in below example. And further not able to see the welcome and Edit child routes.
    1. import { Injectable } from "@angular/core";  
    2. import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router";  
    3.   
    4. @Injectable()  
    5. export class AuthenticationGuard implements CanActivate  {  
    6.       
    7. constructor(private authService: AuthService){}  
    8.   
    9.   
    10.     canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean>|Promise<boolean>|boolean {  
    11.           
    12.         return this.authService.isAuthenticated();  
    13.     //Logic of authenticating user by calling some API service.  
    14.     // For e.g. Here Authservice has a isAuthenticated() method which further  
    15.     // Check user is valid or not.  
    16.     }  
    17. }  
  1. In Module, while creating routes set canActivate as below,
    1. const APP_ROUTES : Routes = [  
    2.         {path:'', component: HomeComponent, canActivate:[ AuthenticationGuard], children:[  
    3.         {path:'', component: WelcomeComponent},  
    4.         {path:'edit', component: EditComponent, }],  
    5.         {path:':id/Logout, component: LogoutComponent},  
    6.   {path:'Login’, component: LoginComponent }  
    7.   
    8.     ]},  
    9. ]  
    10.   
    11. @NgModule({  
    12.     imports:[  
    13.         RouterModule.forChild(APP_ROUTES)  
    14.     ],  
    15.     providers:[          
    16.         AuthenticationGuard  
    17.     ],  
    18.     exports:[  
    19.         RouterModule  
    20.     ]  
    21. })  
    22. export class MyRoutingModule{  
    23.   

CanActivateChild Guard

  1. This guard checks the access on child routes. Take the above example. If the AuthenticationGuard returns false then the user is able to navigate the Home route in below example. And will be able to see its child routes. But not able to move inside welcome or Edit child routes if it returns false.
    1. import { Injectable } from "@angular/core";  
    2. import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router";  
    3.   
    4. @Injectable()  
    5. export class AuthenticationGuard implements CanActivateChild  {  
    6.       
    7. constructor(private authService: AuthService){}  
    8.   
    9.   
    10.     CanActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean>|Promise<boolean>|boolean {  
    11.           
    12.         return this.authService.isAuthenticated();  
    13.     //Logic of authenticating user by calling some API service.  
    14.     // For e.g. Here Authservice has a isAuthenticated() method which further  
    15.     // Check user is valid or not.  
    16.     }  
    17. }  
  1. In Module, while creating routes set canActivateChild as below,
    1. const APP_ROUTES : Routes = [  
    2.         {path:'', component: HomeComponent, canActivateChild:[ AuthenticationGuard], children:[  
    3.         {path:'', component: WelcomeComponent},  
    4.         {path:'edit', component: EditComponent, }],  
    5.         {path:':id/Logout, component: LogoutComponent},  
    6.   {path:'Login’, component: LoginComponent }  
    7.   
    8.     ]},  
    9. ]  
    10.   
    11. @NgModule({  
    12.     imports:[  
    13.         RouterModule.forChild(APP_ROUTES)  
    14.     ],  
    15.     providers:[          
    16.         AuthenticationGuard  
    17.     ],  
    18.     exports:[  
    19.         RouterModule  
    20.     ]  
    21. })  
    22. export class MyRoutingModule{  
    23.   
    24. }  

CanDeactivate Guard

This guard is used when a user makes some changes in a form and by mistake clicks on a menu to navigate to some other route. In this case, it can be implemented to prompt a user that there are some unsaved changes, do you want to navigate away from this page or not.

Here is implementation,

  1. Firstly create a CanDeactivateGuard.service.ts. In this firstly create an interface i.e. CanComponentDeactivate. After that, create CanDeactivateGuard service which further implements CanDeactivate<CanComponentDeactivate> as below,
    1. import { Observable } from "rxjs/Observable";  
    2. import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router";  
    3.   
    4. export interface CanComponentDeactivate {  
    5.   
    6.     canDeactivate:() => Observable<boolean>| Promise<boolean> | boolean;  
    7. }  
    8.   
    9. export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate>{  
    10.   
    11.     canDeactivate(component: CanComponentDeactivate,  
    12.         currentRoute : ActivatedRouteSnapshot,  
    13.         state : RouterStateSnapshot,  
    14.         next? : RouterStateSnapshot) : Observable<boolean>| Promise<boolean> | boolean{  
    15.   
    16.             return component.canDeactivate();  
    17.     }  
    18. }  
  1. Now, in a component where we want prompt functionality implement CanComponentDeactivate interface. For e.g. below EditDataComponent is doing,
    1. import { Component, OnInit } from '@angular/core';  
    2. import { MyService } from '../my.service';  
    3. import { ActivatedRoute, Params } from "@angular/router";  
    4. import { CanComponentDeactivate } from "../../app-candeactivate-guard.service";  
    5. import { Observable } from "rxjs/Observable";  
    6. @Component({  
    7.   selector: 'app-edit',  
    8.   templateUrl: './edit-data.component.html',  
    9.   styleUrls: ['./edit-data.component.css']  
    10. })  
    11. export class EditDataComponent implements OnInit,CanComponentDeactivate {    
    12.   name = '';  
    13.   status = '';  
    14.   originalName = '';  
    15.   originalStatus = '';  
    16.   changed = false;  
    17.   constructor(private myservice: MyService, private activatedRoute: ActivatedRoute) { }  
    18.   ngOnInit() {    
    19.     //call some service to set the original name and staus  
    20.     this.originalName = 'Name from service'// this.myservice.GetName();  
    21.     this.originalStatus = 'Status from service';// this.myservice.GetSatuts();  
    22.     this.name = this.originalName;  
    23.     this.status = this.originalStatus;  
    24.   }  
    25.   onUpdateServer() {  
    26.     this.myService.updateData({name: this.name, status: this.status});  
    27.     this.changed =true;  
    28.   }  
    29.   canDeactivate() :Observable<boolean>| Promise<boolean> | boolean {  
    30.     if((this.name!== this.originalName || this.status !== this.originalStatus) && !this.changed){  
    31.         return confirm("Do you want to discard changes!")  
    32.       }  
    33.     else{  
    34.        return true;  
    35.     }  
    36.   }  
    37. }  
  1. Now, register this guard in routes as below.
    1. const APP_ROUTES: Routes = [  
    2.   {path:'home', component: HomeComponent},   
    3.   {path:'books',   
    4.         canActivateChild :[AuthGuard],  
    5.          component: booksComponent, children: [  
    6.      {path:':id', component: bookComponent },  
    7.      {path:':id/edit', component: EditDataComponent, canDeactivate: [CanDeactivateGuard]},  
    8.   ]},   
    9.   {path:'', component: HomeComponent, pathMatch:'full' },  
    10.   {path:'not-found', component: ErrorPageComponent, data: {message:'Page Not found'} },  
    11.   {path:'**', redirectTo: '/not-found' },  
    12. ];  
    13.   
    14. @NgModule({  
    15.     imports:[RouterModule.forRoot(APP_ROUTES)],  
    16.     exports:[RouterModule]  
    17. })  
    18. export class AppRoutingModule{  
    19.   
    20. }  


Similar Articles