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 guard | Action |
true | navigation process continues. |
false | navigation process stops. |
UrlTree | The current navigation process stops and the new navigation process is initiated according to the URL value |
The Router supports multiple guard methods.
Interfaces | Actions |
canActivate | guards navigation to the root route |
canActivateChild | guards navigation to the child route |
canDeactivate | To mediate navigation away from the current route |
resolve | To perform route data retrieval before route activation |
canMatch | To 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.
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
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.
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.