DEV Community

Cover image for Angular Route Guards Simplified
John Peters
John Peters

Posted on

Angular Route Guards Simplified

Within Angular Routing, we can add a key (canActivate) to each route object as shown below.

{
    path: "dialog",
    component: DialogComponent,
    canActivate: [canActivateService]
},
Enter fullscreen mode Exit fullscreen mode

The Angular Router logic will first call the service we've named canActivateService to determine to proceed further. The canActivateService must implement the CanActivate interface.

CanActivateService

The CanActivate interface ensures a function named canActivate exists. The router calls the canActivate function prior to allowing the route to continue.

import { ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router";
import { Injectable } from "@angular/core";
import { CanActivate } from "@angular/router";
import { RestangularService } from "./restangular.service";
import { EventService } from "./event.service";

@Injectable({
   providedIn: "root"
})
export class canActivateService implements CanActivate { 

constructor(private rs: RestangularService, private es: EventService) {}
   // returns a true or false promise
   canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
      return this.rs.getIdentityInfo();
   }
}
Enter fullscreen mode Exit fullscreen mode

Can Promises be used?

In the code above, we are using a Restangular HTTP request (Observable) to get user info. We've wrapped it in a promise so that the canActivate function passes back a Promise to the router.

   // returns a true or false promise
   getIdentityInfo(): Promise<boolean> {
      // Convert the observable to a promise.
      let prm = new Promise<boolean>((resolve, reject) => {
         // this is the observable
         this.Restangular.one(this.IDENTITYINFO)
            .get()
            .subscribe(
               result => {
                  this.EventService.IdentityInfoEvent.emit(result);
                  // resolve the promise
                  resolve(true);
               },
               error => {
                  // we take control on error showing an error
                  this.EventService.OpenError(ErrorModel.Create(error));
               }
            );
      });
      return prm;
   }
Enter fullscreen mode Exit fullscreen mode

When we resolve the promise to true, the user is allowed to navigate, otherwise, and error is shown.

We are easily able to add other criteria to the route guard, as we've neatly separated the code into following the SRP principal.

In the future we'll add canDeactivate which decides if the user can leave the page (in case they haven't saved their data).

All told; a pretty simple and nice routing feature out-of-the-angular-box.

JWP2020

Top comments (0)