Routing guard in Angular Router.

Routing guard in Angular Router.

What is Routing?

There are numerous UI pages for user interaction in an application. Let's use an online shopping app as an example. This app has a home page, a cart page, a wishlist page, and a sign-in/login page. Let's say we added the item to our shopping cart since we wanted to purchase it from the app. On this page, the item we added to our shopping cart is not shown. To view all the items we wanted to purchase, we must go to the cart page, correct? Therefore, we require a tool called Router to navigate to pages.

What is Routing Guard💪?

As the title shows the answer. In an application, there are a few pages that are only accessible to authenticated users. so for some pages that are only accessible to authenticated users, there is a guard to prevent unauthorized access. Routing guard is a tool we can do that with.

The value that the guard returns controls the router's behaviour.

Value from guardAction
truenavigation process continues.
falsenavigation process stops.
UrlTreeThe current navigation process stops and the new navigation process is initiated according to the URL value

The Router supports multiple guard methods.

InterfacesActions
canActivateguards navigation to the root route
canActivateChildguards navigation to the child route
canDeactivateTo mediate navigation away from the current route
resolveTo perform route data retrieval before route activation
canMatchTo control whether a Route should be used at all, even if the path matches the URL segment

We are going to see an example on canActivate Interface.

Let's take an example of a shopping app. It has 4 pages i.e. Home, Fashion, Food, and Cart. The user can navigate any page they want to.

But Let's say here we do not want to give access to the Cart page to unauthorized users. So The Routing Guard comes into the picture.

We will add the canActivate guard to the application to guard our Cart page.

  1. We need to create a service.ts file for implementing the canActivate method

     ng g s cart-guard //command for creating the cart-guard.service.ts file
    
     import { Injectable } from '@angular/core';
     import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
    
     @Injectable({
       providedIn: 'root'
     })
     export class CartGuardService implements CanActivate {
    
       constructor() { }
       canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot):boolean{
         return true;
       }
    

CartGuardService class implements the interface CanActivate and the canActivate method have two parameters ActivatedRouteSnapshot and RouterStateSnapshot will return Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree

let's return a boolean for now and implement it.

//app-module.ts
  providers: [CartGuardService],//for registering the routing guard
//app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { FashionComponent } from './fashion/fashion.component';
import { FoodComponent } from './food/food.component';
import { CartComponent } from './cart/cart.component';
import { CartGuardService } from './cart-guard.service';

const routes: Routes = [
  {path:"home",component:HomeComponent},
  {path:"fashion",component:FashionComponent},
  {path:"food",component:FoodComponent},
  {path:"cart",component:CartComponent,canActivate:[CartGuardService]},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

in the app-routing.module.ts to the CartComponent routing, add the canActivate method followed by the class inside an array. also import the CartGuardService

💡
if the canActivate method returns true, the user is allowed to navigate to all the pages and not allowed if returns false or the user stays put.

Let's add condition to our Routing guard for authentication. If the User is logged in it can navigate to the cart page, if not an error will show on the console.

Create an auth.service.ts and inject it to the CartGuardService class.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  constructor() { }
  loggedin:boolean = false;
  isAuthenticated(){
    return this.loggedin;
  }
}
//app-module.ts  
providers: [CartGuardService,AuthService],//registering AuthService
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class CartGuardService implements CanActivate {

  constructor(private authservice:AuthService) { }
  canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot):boolean{
    if(this.authservice.isAuthenticated()){
      console.log("User is Logged in");
      return true      
    }else{
      console.error("User is not LoggedIn");
      return false;
    }
  }
}

Here in CartGuardService, create an instance of AuthService, and authenticate the user based on the condition.

💡
in the AuthService the loggedin value is set to be false so we will get the console error.

You can see the Console is showing an error of 'User is not LoggedIn'.

This is how we can guard our component.