Tim Deschryver

The difference between the canActivate and canActivateChild guards

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.

@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.

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

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.

@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.

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

Share on Twitter Discuss on Twitter Edit on GitHub

Send Tim a message