Skip to main content

Angular Child Routes

Introduction

In Angular applications, as your app grows in complexity, you'll often need to organize your routes in a hierarchical structure. Child routes (also called nested routes) allow you to create parent-child relationships between routes, enabling you to build more complex UIs with nested components. This approach helps you create more modular and maintainable applications.

Child routes are particularly useful when you want to:

  • Create a layout that has its own navigation system
  • Organize related features within a section of your application
  • Build a master-detail interface where a list and its detail views share a common layout

Understanding the Basics

In Angular's routing system, child routes are defined within a parent route configuration. The child components are then rendered inside the parent component's template using the <router-outlet> directive.

Basic Structure

Here's how child routes are structured in Angular:

typescript
const routes: Routes = [
{
path: 'parent',
component: ParentComponent,
children: [
{ path: 'child1', component: Child1Component },
{ path: 'child2', component: Child2Component }
]
}
];

With this configuration:

  • /parent will load the ParentComponent
  • /parent/child1 will load the ParentComponent with Child1Component nested inside it
  • /parent/child2 will load the ParentComponent with Child2Component nested inside it

Creating Your First Child Routes

Let's walk through a step-by-step example of implementing child routes in an Angular application.

Step 1: Set up the Components

First, let's create the necessary components:

bash
ng generate component products
ng generate component products/product-list
ng generate component products/product-detail

Step 2: Configure the Routes

Next, set up the route configuration in your routing module:

typescript
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProductsComponent } from './products/products.component';
import { ProductListComponent } from './products/product-list/product-list.component';
import { ProductDetailComponent } from './products/product-detail/product-detail.component';

const routes: Routes = [
{
path: 'products',
component: ProductsComponent,
children: [
{ path: '', component: ProductListComponent },
{ path: ':id', component: ProductDetailComponent }
]
}
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

Step 3: Setup the Parent Component Template

The parent component needs a <router-outlet> to display its child components:

typescript
// products.component.ts
import { Component } from '@angular/core';

@Component({
selector: 'app-products',
template: `
<div class="products-container">
<h2>Products Section</h2>
<div class="content">
<!-- Child components will be rendered here -->
<router-outlet></router-outlet>
</div>
</div>
`,
styleUrls: ['./products.component.css']
})
export class ProductsComponent { }

Step 4: Implement the Child Components

Now implement the child components:

typescript
// product-list.component.ts
import { Component } from '@angular/core';

@Component({
selector: 'app-product-list',
template: `
<h3>Product List</h3>
<ul>
<li *ngFor="let product of products">
<a [routerLink]="['/products', product.id]">{{ product.name }}</a>
</li>
</ul>
`
})
export class ProductListComponent {
products = [
{ id: 1, name: 'Phone XL' },
{ id: 2, name: 'Phone Mini' },
{ id: 3, name: 'Phone Standard' }
];
}
typescript
// product-detail.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
selector: 'app-product-detail',
template: `
<div *ngIf="product">
<h3>Product Details</h3>
<p>ID: {{ product.id }}</p>
<p>Name: {{ product.name }}</p>
<button (click)="goBack()">Back to List</button>
</div>
`
})
export class ProductDetailComponent implements OnInit {
product: any;

constructor(private route: ActivatedRoute) {}

ngOnInit() {
const productId = this.route.snapshot.paramMap.get('id');
// In a real app, you would fetch the product from a service
this.product = {
id: productId,
name: `Product ${productId}`
};
}

goBack() {
window.history.back();
}
}

To navigate between child routes, you can use the routerLink directive or the Router service:

html
<!-- For the product list -->
<a [routerLink]="['/products']">All Products</a>

<!-- For a specific product -->
<a [routerLink]="['/products', product.id]">{{ product.name }}</a>

Using Router Service

typescript
import { Router } from '@angular/router';

@Component({...})
export class SomeComponent {
constructor(private router: Router) {}

navigateToProductList() {
this.router.navigate(['/products']);
}

navigateToProductDetail(productId: number) {
this.router.navigate(['/products', productId]);
}
}

Advanced Child Routes Concepts

Multiple Router Outlets with Named Routes

You can have multiple router outlets in the same component by giving them different names:

typescript
// routing configuration
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
children: [
{ path: 'stats', component: StatsComponent },
{
path: 'notifications',
component: NotificationsComponent,
outlet: 'sidebar'
}
]
}
];
html
<!-- In dashboard.component.html -->
<div class="main">
<router-outlet></router-outlet>
</div>
<div class="sidebar">
<router-outlet name="sidebar"></router-outlet>
</div>

Lazy Loading Child Routes

For larger applications, you can use lazy loading with child routes to improve performance:

typescript
// app-routing.module.ts
const routes: Routes = [
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}
];
typescript
// admin-routing.module.ts
const routes: Routes = [
{
path: '',
component: AdminComponent,
children: [
{ path: 'dashboard', component: AdminDashboardComponent },
{ path: 'users', component: AdminUsersComponent }
]
}
];

Real-World Example: E-commerce Dashboard

Let's build a more comprehensive example of a dashboard with child routes:

Project Structure

app/
├── dashboard/
│ ├── dashboard.component.ts
│ ├── dashboard.component.html
│ ├── overview/
│ │ └── overview.component.ts
│ ├── sales/
│ │ └── sales.component.ts
│ └── inventory/
│ └── inventory.component.ts
└── app-routing.module.ts

Route Configuration

typescript
// app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{
path: 'dashboard',
component: DashboardComponent,
children: [
{ path: '', redirectTo: 'overview', pathMatch: 'full' },
{ path: 'overview', component: OverviewComponent },
{ path: 'sales', component: SalesComponent },
{ path: 'inventory', component: InventoryComponent }
]
}
];

Dashboard Layout

html
<!-- dashboard.component.html -->
<div class="dashboard-container">
<div class="sidebar">
<h3>Dashboard Navigation</h3>
<nav>
<ul>
<li><a routerLink="overview" routerLinkActive="active">Overview</a></li>
<li><a routerLink="sales" routerLinkActive="active">Sales</a></li>
<li><a routerLink="inventory" routerLinkActive="active">Inventory</a></li>
</ul>
</nav>
</div>

<div class="content">
<router-outlet></router-outlet>
</div>
</div>
css
/* dashboard.component.css */
.dashboard-container {
display: flex;
height: 100%;
}

.sidebar {
width: 200px;
padding: 20px;
background-color: #f5f5f5;
}

.content {
flex: 1;
padding: 20px;
}

.active {
font-weight: bold;
color: #007bff;
}

This structure creates a dashboard with a persistent sidebar and different content areas that change based on the selected navigation item.

Common Issues and Solutions

Child Component Not Displaying

If your child component isn't displaying, check that:

  1. You've included a <router-outlet> in the parent component
  2. The paths in your route configuration are correct
  3. The child route is properly registered under the children array of the parent route

Route Parameters in Child Routes

To access route parameters in a child route, you can use the ActivatedRoute service:

typescript
import { ActivatedRoute } from '@angular/router';

@Component({...})
export class ChildComponent implements OnInit {
constructor(private route: ActivatedRoute) {}

ngOnInit() {
this.route.paramMap.subscribe(params => {
const id = params.get('id');
// use the id parameter
});
}
}

Summary

Child routes in Angular provide a powerful way to organize your application's UI into nested hierarchies. They allow you to:

  1. Create complex, multi-level navigation structures
  2. Keep related functionality grouped together
  3. Build modular interfaces with reusable layouts
  4. Improve the user experience with more intuitive navigation patterns

By understanding how to properly configure and implement child routes, you can build more maintainable and user-friendly Angular applications.

Additional Resources

Exercises

  1. Create a basic admin panel with child routes for "Users", "Settings", and "Reports" sections.
  2. Implement a master-detail view using child routes where clicking on an item in a list shows its details in a nested route.
  3. Build a multi-step form wizard using child routes where each step is a different route within a parent container.
  4. Extend the e-commerce dashboard example with additional features like route guards to protect certain child routes.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)