How to Use canActivateChild in Ionic?

Alexey Karimov

It’s common to encounter a problem in Ionic Angular apps with nested routes: The parent route is protected, but the child routes aren’t. In such a scenario, users can still land on or navigate between child views that should have been blocked.

Securing the parent route alone doesn’t stop access to child routes. If that’s the issue you’re facing, then you might want to use canActivateChild

In this guide, we’ll break down what canActivateChild is, how it compares to canActivate, and how to implement it effectively in an Ionic Angular project.

What is canActivateChild?

canActivateChild is a route guard in Angular that runs before any child route is activated. It’s part of Angular’s router system and is especially useful in Ionic apps where navigation often involves nested routes, like tabs or sectioned detail pages.

To use it, you implement the CanActivateChild interface in a service. The guard receives the current route (ActivatedRouteSnapshot) and the navigation state (RouterStateSnapshot). From there, you can check conditions, such as whether a user is authenticated, has the right role, or meets other business logic, and return a result.

The return value can be:

  • true to allow access
  • false to block navigation
  • UrlTree to redirect the user (e.g., to a login screen)
  • Observable or Promise that resolves to any of the above

In practice, canActivateChild is applied to a parent route using the canActivateChild key in the route configuration. When set, the guard will run whenever a user navigates to any child, whether they enter directly or move between child routes.

free trial banner

How canActivateChild Differs from canActivate?

Now that you are aware of canActivateChild, it’s common to have a question: how is it different from canActivate?

Both are route guards used to control navigation, but they trigger at different points in the routing lifecycle. Here’s the key behavioral difference:

canActivate: It runs before the route (and its component) is activated. It’s typically used to protect top-level routes. If you apply canActivate to a parent route, and the user navigates to a child, the guard runs only once, when the parent is loaded.

canActivateChild: As explained before, it runs before any of the child routes are activated, but only when applied to a parent route. It’s triggered when the user navigates to or between child routes. The guard runs every time a child route is activated, even if the parent component is already active.

canActivateChild Use Cases 

All set to use canActivateChild? Before you implement it, here are some common use cases so you can better understand when and why it’s helpful.

  • Protecting profile or settings tabs: Tabs like /tabs/profile or /tabs/settings often require the user to be authenticated. Applying canActivateChild to the parent /tabs route lets you block unauthorized access to all protected tabs at once.
  • Blocking access based on user roles: If only admins should see /tabs/analytics, the guard can check roles before allowing the route. This prevents users from accessing pages not meant for them, even through direct URL entry.
  • Preventing access to unfinished setup flows: For multi-step onboarding or setup pages under a single parent route, canActivateChild can check if the user has completed earlier steps before allowing access to later ones.
  • Securing deeply nested routes in feature modules: Instead of repeating canActivate on every child route, applying canActivateChild at the parent level reduces duplication and centralizes control.

Implementing canActivateChild in an Ionic App

To implement canActivateChild in an Ionic project, you’ll typically define a simple guard and apply it to a route that contains children. Here’s how that looks in practice.

Note: The code below is simplified and meant for reference to help understand the core idea.

// auth.guard.ts
@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivateChild {
  constructor(private authService: AuthService, private router: Router) {}

  canActivateChild(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean | UrlTree {
    if (this.authService.isLoggedIn()) {
      return true;
    }
    return this.router.createUrlTree(['/login']);
  }
}

The AuthGuard service checks if the user is logged in by calling authService.isLoggedIn(). If they are, it allows access to the child route by returning true. If not, it returns a UrlTree to redirect the user to the login page. This logic runs every time a child route under the guarded parent is accessed.

Next, you apply the guard to the parent route:

// app-routing.module.ts
const routes: Routes = [
  {
    path: 'tabs',
    component: TabsPage,
    canActivateChild: [AuthGuard],
    children: [
      { path: 'home', component: HomePage },
      { path: 'profile', component: ProfilePage },
      { path: 'settings', component: SettingsPage }
    ]
  }
];

This configuration guards all child routes under /tabs. So if someone tries to visit /tabs/profile or navigates from one tab to another, the AuthGuard will run first. If it denies access, the child component won’t load. 

This setup is particularly useful in Ionic apps where tabs or nested pages need to be protected based on login status or roles.

Note: If you’re using Ionic’s default tab template, child routes are often managed through <ion-tabs> with named outlets. However, canActivateChild still applies when routes are defined under a shared parent.

Wrapping Up

When using canActivateChild, keep your access checks clean and focused. Avoid mixing UI logic or complex conditions. The guard’s job is simple: decide if the child route should load.

As a best practice, offload checks like login status or user roles to dedicated services. This keeps your guard logic minimal and easier to maintain.

Always prefer returning a UrlTree over false when blocking access. It gives you more control by letting you redirect users to specific routes like login or error pages. Apply canActivateChild at the parent level only when most child routes need the same protection. If access rules differ between children, use canActivate individually.