The difference between the canActivate and canActivateChild guards

Post Editor

In this article I explain the difference between the canActivate and canActivateChild guards.

2 min read
post

The difference between the canActivate and canActivateChild guards

In this article I explain the difference between the canActivate and canActivateChild guards.

post
post
2 min read

canActivate
Link to this section

Interface that a class can implement to be a guard deciding if a route can be activated. If all guards return true, navigation will continue. If any guard returns false, navigation will be cancelled. If any guard returns a UrlTree, current navigation will be cancelled and a new navigation will be kicked off to the UrlTree returned from the guard.

The canActivate guard decides if route can be navigated to, which results in the creation of the route's component.

To implement the guard, create a new class and implement the CanActivate interface.
The interface can return a boolean (as a boolean, a promise, or an Observable) or the guard can navigate to another route.
If it returns a truthy value, the component will be created, otherwise it will not and the navigation gets canceled.

<>Copy
@Injectable({ providedIn: "root", }) export class OnlyDigitsGuard implements CanActivate { canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ){ return /^\d+$/.test(next.params.id); }

To guard a route, add the guard to the canActivate property while declaring the routes in the application.

<>Copy
const routes: Routes = [ { path: 'parent', component: ParentComponent, canActivate: [OnlyDigitsGuard], }, ]

canActivateChild
Link to this section

Interface that a class can implement to be a guard deciding if a child route can be activated. If all guards return true, navigation will continue. If any guard returns false, navigation will be cancelled. If any guard returns a UrlTree, current navigation will be cancelled and a new navigation will be kicked off to the UrlTree returned from the guard.

The canActivateChild guard, serves the same purpose as the canActivate guard and can prevent a route navigation.
The API to create the guard is the same, but for the canActivateChild guard you have to implement the CanActivateChild interface.

<>Copy
@Injectable({ providedIn: "root", }) export class OnlyDigitsGuard implements CanActivateChild { canActivateChild( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ){ return /^\d+$/.test(next.params.id); }

To add the guard to the routes, use the canActivateChild property.
Doing this will guard all the children's routes.

<>Copy
const routes: Routes = [ { path: "parent", component: ParentComponent, canActivateChild: [OnlyDigitsGuard], children: [...], }, ];

The differences
Link to this section

  • canActivate will only execute when the parent component is not yet created. For example, if we navigate to the parent route it will be called, if we then navigate to a child route it will not. If we directly navigate to the child route, the canActivate guard will also be executed.
  • canActivateChild will always be executed while navigating to/between child routes. For example, if we're at a child route child/1 and we navigate to child/2, the guard will get executed. If we directly navigate to a child route, the guard will also get called. If we navigate to the parent route, the canActivateChild guard will not be fired.
  • because canActivate is guarding the parent route, the child parameters (and data) are not available on the ActivatedRouteSnapshot of the canActivate guard. To be able to access the child parameters, we have to drill down the child components on the RouterStateSnapshot.

Nice to knows
Link to this section

  • because the parent component gets created first, the canActivate guard will always be called first.
  • if we directly navigate to a child component and the child guard returns a falsy value then the parent component will also not be created, because the navigation is cancelled when one of the guards return a falsy value.
  • when the canActivate guard returns a falsy value, then the canActivateChild guard will not be called.
  • the canActivateChild guard can be rewritten as a canActivate guard on every child route.

Example application
Link to this section

Share

About the author

author_image

NgRx team member

author_image

About the author

Tim Deschryver

NgRx team member

About the author

author_image

NgRx team member

Looking for a JS job?
Job logo
Fullstack (Angular, Node.js) Developer

Nextian Corp.

Worldwide
Remote
$84k - $107k
Job logo
Application Developer (Angular)

Karsun Solutions, LLC

Worldwide
Remote
$104k - $132k
Job logo
Angular Developer

Ryan Consulting Group

Worldwide
Remote
$77k - $80k
More jobs

Featured articles

Angularpost
17 January 202323 min read
Improve page performance and LCP with NgOptimizedImage

Explore mechanisms of NgOptimizedImage directive to improve overall page performance, targeting especially the Largest Contentful Paint (LCP) metric from Core Web Vitals. Enhance pages, make the best user experience and improve the web.