How to use canActivateChild in Angular
The canActivateChild functional route guard is one of the most important concepts of Angular.
1. The canActivateChild
route guard controls, if the current user is allowed to activate a child of the component. It accepts Array <CanActivateChildFn>
type data.
2. In the application, the canActivateChild
is used for user authorization.
3. We apply the canActivateChild
guard to the parent route.
4. Whenever the user try to navigate child route, Angular activate this route guard.
5. The route guard checks some conditions in the method and it decides whether the current user can access the route path or not.
6. If the current user navigates the child route, and the guard inside canActivateChild
returns true, then the user can access the URL.
7. Whenever the method returns false to the current user, then the user can not access the URL.
Code Snippet:
canActivateChild: [ (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => inject(AuthGuardService).canActivateChild(route, state) ]
The inject
function helps to inject external dependencies in functions. We call canActivateChild method inside inject function.
Using canActivateChild:
1: We create an auth-guard.service file, and using the canActivateChild
route guard to control child component access. In this service file, we create one canActivateChild
method. In this method, we check the user authorization to a certain path.
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { let loggedInUser = this.authService.getLoggedInUser(); if (oggedInUser.role === 'Admin' || loggedInUser.role === 'Customer') { return true; } else { alert("You are not authorized to visit the customer section!") return false; } }
2: In Routing module, We use the canActivateChild
route guard in the parent route, where we need to control access for users.
path: 'customer', loadChildren: () => import('../customer/customer.module').then(mod => mod.CustomerModule), canActivateChild: [ (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => inject(AuthGuardService).canActivateChild(route, state) ]
Complete Example:
In this example, I will create one demo application and inside I will create login and dashboard components for use canActivateChild.
1: I created two feature modules inside the dashboard folder and created a navigation for accessing feature modules in the dashboard component.
2: In the auth.service file, I created three users and provided different roles. I will provide access to the feature module on the basis of the role. Admin -> login - admin, pass - admin (Supper admin) employee -> login - santosh, pass - s123(employee) customer -> login - mohan, pass - m123
3: I configured the canActivateChild
method in the dashboard.routing.module. In the module, I added two route paths for the access feature module, one is the employee path and the other is the customer path.
4: I added the canActivateChild
method in the customer path to prevent access when employees login. Only the admin and customer can access the customer route path.
5: When an employee login, he can not access the customer feature module. Because he is not authorized to access.
dashboard.routing.module.ts
import { NgModule, inject } from '@angular/core'; import { ActivatedRouteSnapshot, RouterModule, RouterStateSnapshot, Routes } from '@angular/router'; import { AuthGuardService } from '../authentication/services/auth-guard.service'; const dashboardRoutes: Routes = [ { path: 'employee', loadChildren: () => import('../employee/employee.module').then(mod => mod.EmployeeModule) }, { path: 'customer', loadChildren: () => import('../customer/customer.module').then(mod => mod.CustomerModule), canActivateChild: [ (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => inject(AuthGuardService).canActivateChild(route, state) ], } ]; @NgModule({ imports: [ RouterModule.forChild(dashboardRoutes) ], exports: [ RouterModule ] }) export class DashboarRoutingModule { }
auth-guard.service.ts
import { Injectable } from '@angular/core'; import { Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable() export class AuthGuardService { constructor(private authService: AuthService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { let url: string = state.url; if (this.authService.isUserLoggedIn()) { return true; } this.authService.setRedirectUrl(url); this.router.navigate([this.authService.getLoginUrl()]); return false; } canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { let loggedInUser = this.authService.getLoggedInUser(); if (loggedInUser.role === 'Admin' || loggedInUser.role === 'Customer') { return true; } else { console.log('Unauthorized to open link: ' + state.url); alert("You are not authorized to visit the customer section!") return false; } } }
auth.service.ts
const USERS = [ new User(1, 'admin', 'admin', 'Admin'), new User(2, 'santosh', 's123', 'Employee'), new User(2, 'mohan', 'm123', 'Customer') ];
dashboard.component.html
<div class="row"> <div class="col-md-12 header-menu"> <ul> <li><a routerLink="/">Home</a></li> <li><a routerLink="/dashboard/employee" routerLinkActive="active">Employee</a></li> <li><a routerLink="/dashboard//customer" routerLinkActive="active">Customer</a></li> </ul> <div class="logout"> <logout></logout> </div> </div> <div class="col-md-12 pt-4"> <h4>Dashboard:: webrecto.com</h4> <router-outlet></router-outlet> </div> </div>
Find the print screen of the output.
I am login from santosh user id
When an employee user clicks on the customer path from navigation, he can not access it and will find the unauthorized user access message.