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
CanActivateChildcontrols 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
ObservableorPromisefor asynchronous checks. CanActivateandCanActivateChildcan 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
CanActivateChildis an Angular route guard used to control access to the child routes of a parent route. In modern Angular, it is commonly implemented usingCanActivateChildFnand configured withcanActivateChild. 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.