← Back to Articles         
What is CanActivateChild?

What is CanActivateChild?

Published on 30 Sep 2026     8 min read Angular
Route Guards

What is CanActivateChild in Angular?

What is CanActivateChild?

CanActivateChild is an Angular route guard used to control whether a user can navigate to the child routes of a parent route.

In modern Angular, it is commonly implemented using:

CanActivateChildFn

For example, suppose Admin has several child pages:

/admin
/admin/users
/admin/reports
/admin/settings

Instead of adding the same canActivate guard to every child route, we can protect the child routes using:

canActivateChild: [adminGuard]

Conceptually:

/admin
   │
   ├── /users
   ├── /reports
   └── /settings
          ↑
     CanActivateChild

Full Simple Sample Program

We will create an Admin section with three child routes:

/admin/users
/admin/reports
/admin/settings

auth.service.ts

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

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

  private role = 'Admin';

  isAdmin(): boolean {
    return this.role === 'Admin';
  }
}

admin.guard.ts

import { inject } from '@angular/core';
import {
  CanActivateChildFn,
  Router
} from '@angular/router';

import { AuthService } from './auth.service';

export const adminChildGuard: CanActivateChildFn =
  (childRoute, state) => {

    const authService = inject(AuthService);
    const router = inject(Router);

    if (authService.isAdmin()) {
      return true;
    }

    return router.createUrlTree(['/access-denied']);
  };

admin.ts

import { Component } from '@angular/core';
import {
  RouterLink,
  RouterOutlet
} from '@angular/router';

@Component({
  selector: 'app-admin',
  standalone: true,
  imports: [
    RouterLink,
    RouterOutlet
  ],
  template: `
    <h2>Admin</h2>

    <nav>
      <a routerLink="users">Users</a> |
      <a routerLink="reports">Reports</a> |
      <a routerLink="settings">Settings</a>
    </nav>

    <hr>

    <router-outlet></router-outlet>
  `
})
export class Admin {
}

users.ts

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

@Component({
  selector: 'app-users',
  standalone: true,
  template: `
    <h3>Users</h3>
    <p>Manage application users.</p>
  `
})
export class Users {
}

reports.ts

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

@Component({
  selector: 'app-reports',
  standalone: true,
  template: `
    <h3>Reports</h3>
    <p>View application reports.</p>
  `
})
export class Reports {
}

settings.ts

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

@Component({
  selector: 'app-settings',
  standalone: true,
  template: `
    <h3>Settings</h3>
    <p>Manage application settings.</p>
  `
})
export class Settings {
}

access-denied.ts

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

@Component({
  selector: 'app-access-denied',
  standalone: true,
  template: `
    <h2>Access Denied</h2>

    <p>
      You do not have permission to access this page.
    </p>
  `
})
export class AccessDenied {
}

app.routes.ts

import { Routes } from '@angular/router';

import { Admin } from './admin';
import { Users } from './users';
import { Reports } from './reports';
import { Settings } from './settings';
import { AccessDenied } from './access-denied';

import { adminChildGuard } from './admin.guard';

export const routes: Routes = [
  {
    path: 'admin',
    component: Admin,

    canActivateChild: [
      adminChildGuard
    ],

    children: [
      {
        path: 'users',
        component: Users
      },
      {
        path: 'reports',
        component: Reports
      },
      {
        path: 'settings',
        component: Settings
      }
    ]
  },

  {
    path: 'access-denied',
    component: AccessDenied
  }
];

app.ts

import { Component } from '@angular/core';
import {
  RouterLink,
  RouterOutlet
} from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterLink,
    RouterOutlet
  ],
  template: `
    <h1>My Application</h1>

    <a routerLink="/admin/users">
      Admin Users
    </a>

    <hr>

    <router-outlet></router-outlet>
  `
})
export class App {
}

app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes)
  ]
};

Explanation

The important configuration is:

{
  path: 'admin',
  component: Admin,

  canActivateChild: [adminChildGuard],

  children: [
    {
      path: 'users',
      component: Users
    },
    {
      path: 'reports',
      component: Reports
    },
    {
      path: 'settings',
      component: Settings
    }
  ]
}

canActivateChild applies the guard to navigation into the child routes.


How Does It Work?

Suppose the user enters:

/admin/users

Angular processes the route hierarchy:

/admin
   ↓
Parent route
   ↓
/users
   ↓
Child route
   ↓
CanActivateChild
   ↓
adminChildGuard
   ↓
Is user Admin?

If:

authService.isAdmin()

returns:

true

the guard returns:

return true;

and Users is activated.

/admin/users
      ↓
adminChildGuard
      ↓
isAdmin() = true
      ↓
Users Component

What Happens if the User Is Not Admin?

Suppose:

private role = 'User';

Then:

authService.isAdmin()

returns false.

The guard returns:

return router.createUrlTree(['/access-denied']);

Flow:

/admin/reports
       ↓
CanActivateChild
       ↓
adminChildGuard
       ↓
Role = User
       ↓
Not authorized
       ↓
/access-denied

Why Use CanActivateChild?

Suppose there are 10 Admin routes.

Without CanActivateChild, you might repeat:

{
  path: 'users',
  component: Users,
  canActivate: [adminGuard]
},
{
  path: 'reports',
  component: Reports,
  canActivate: [adminGuard]
},
{
  path: 'settings',
  component: Settings,
  canActivate: [adminGuard]
}

This works, but repeats the guard.

With CanActivateChild:

{
  path: 'admin',
  component: Admin,

  canActivateChild: [adminChildGuard],

  children: [
    {
      path: 'users',
      component: Users
    },
    {
      path: 'reports',
      component: Reports
    },
    {
      path: 'settings',
      component: Settings
    }
  ]
}

One guard protects the child-route section.


CanActivate vs CanActivateChild

This is the main interview distinction.

CanActivate CanActivateChild
Protects a route Protects navigation to child routes
Applied using canActivate Applied using canActivateChild
CanActivateFn CanActivateChildFn
Often used for individual protected routes Useful for groups of nested routes

CanActivate

{
  path: 'admin',
  component: Admin,
  canActivate: [authGuard]
}

Question:

Can the user activate /admin?

CanActivateChild

{
  path: 'admin',
  component: Admin,
  canActivateChild: [adminChildGuard],

  children: [
    {
      path: 'users',
      component: Users
    }
  ]
}

Question:

Can the user activate /admin/users?


Can We Use Both?

Yes.

This is a useful design when the parent itself needs protection and its child routes need additional protection.

{
  path: 'admin',
  component: Admin,

  canActivate: [
    authGuard
  ],

  canActivateChild: [
    adminChildGuard
  ],

  children: [
    {
      path: 'users',
      component: Users
    },
    {
      path: 'reports',
      component: Reports
    }
  ]
}

Conceptually:

/admin/users
      ↓
canActivate
      ↓
Is user authenticated?
      ↓
Yes
      ↓
canActivateChild
      ↓
Can user access Admin children?
      ↓
Yes
      ↓
Users

For example:

authGuard
    ↓
Authentication


adminChildGuard
    ↓
Authorization

What Parameters Does CanActivateChildFn Receive?

A functional guard looks like:

export const adminChildGuard: CanActivateChildFn =
  (childRoute, state) => {

    // logic

  };

It receives:

childRoute

Information about the child route being activated.

For example:

childRoute.params
childRoute.queryParams
childRoute.data

state

Information about the requested router state.

For example:

state.url

If the user navigates to:

/admin/users

then:

state.url

will represent that requested URL.


What Can CanActivateChild Return?

Like CanActivate, it can return:

Allow

return true;

Block

return false;

Redirect

return router.createUrlTree(['/access-denied']);

It can also return asynchronous results through:

Promise
Observable

Older Angular: Class-Based CanActivateChild

Older Angular applications commonly used a class:

import { Injectable } from '@angular/core';
import {
  CanActivateChild,
  Router
} from '@angular/router';

import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class AdminGuard implements CanActivateChild {

  constructor(
    private authService: AuthService,
    private router: Router
  ) {
  }

  canActivateChild(): boolean {

    if (this.authService.isAdmin()) {
      return true;
    }

    this.router.navigate(['/access-denied']);

    return false;
  }
}

Then:

{
  path: 'admin',
  component: Admin,
  canActivateChild: [AdminGuard],

  children: [
    {
      path: 'users',
      component: Users
    }
  ]
}

Modern Angular commonly uses:

CanActivateChildFn

with inject().


Important Security Point

Like CanActivate, CanActivateChild only controls Angular client-side navigation.

It does not secure your ASP.NET Core Web API.

For example, even if Angular protects:

/admin/users

your API should independently protect:

GET /api/admin/users

For example:

[Authorize(Roles = "Admin")]
[HttpGet]
public IActionResult GetUsers()
{
    // ...
}

Think:

Angular CanActivateChild
          ↓
Controls child-route navigation


ASP.NET Core [Authorize]
          ↓
Enforces actual API authorization

Key Points

  • CanActivateChild controls access to child routes.
  • Modern Angular uses:
CanActivateChildFn
  • Configure it on the parent route:
canActivateChild: [adminChildGuard]
  • It avoids repeating the same guard on every child route.
  • true → allow navigation.
  • false → cancel navigation.
  • Redirect result → navigate elsewhere.
  • It can use Observable or Promise for asynchronous checks.
  • CanActivate and CanActivateChild can be used together.
  • It does not replace backend security.

Interview Questions and Answers

1. What is CanActivateChild?

CanActivateChild is an Angular route guard used to determine whether a user can navigate to the child routes of a parent route.


2. How do you configure it?

{
  path: 'admin',
  component: Admin,

  canActivateChild: [adminChildGuard],

  children: [
    {
      path: 'users',
      component: Users
    }
  ]
}

3. What is the difference between CanActivate and CanActivateChild?

CanActivate protects a route itself, while CanActivateChild protects navigation to its child routes.

CanActivate
    ↓
Can I enter this route?


CanActivateChild
    ↓
Can I enter its child routes?

4. Why use CanActivateChild instead of CanActivate on every child?

It avoids repeating the same guard:

canActivateChild: [adminChildGuard]

can protect multiple child routes from the parent configuration.


5. Can we use CanActivate and CanActivateChild together?

Yes.

{
  path: 'admin',

  canActivate: [authGuard],

  canActivateChild: [adminChildGuard],

  children: [...]
}

For example, CanActivate can check authentication while CanActivateChild applies authorization rules to child pages.


6. What does CanActivateChild return?

It can return an allowed/blocked/redirect result synchronously or asynchronously. Common examples are:

return true;
return false;

or:

return router.createUrlTree(['/access-denied']);

Interview-ready answer

CanActivateChild is an Angular route guard used to control access to the child routes of a parent route. In modern Angular, it is commonly implemented using CanActivateChildFn and configured with canActivateChild. It is useful when several child routes require the same authentication or authorization rule because the guard can be configured once on the parent instead of repeated on every child route.

← Back to Articles