LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 3016 min read

Route Parameters & Nested Routes

Build routes with dynamic parameters, read them reactively, and nest child routes inside a parent layout.

Dynamic Route Parameters

A colon-prefixed segment in a route's path becomes a dynamic parameter, matching any value in that position.

export const routes: Routes = [
{ path: 'products/:id', component: ProductDetailComponent },
];
// /products/42 → paramMap.get('id') === '42'

Reading Params with ActivatedRoute

The ActivatedRoute service exposes the current route's parameters as an Observable, since Angular can reuse the same component instance across param changes (e.g. navigating from /products/1 to /products/2).

import { Component, OnInit, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { switchMap } from 'rxjs/operators';
@Component({ selector: 'app-product-detail', standalone: true, template: `...` })
export class ProductDetailComponent implements OnInit {
private route = inject(ActivatedRoute);
private productsService = inject(ProductsService);
product: Product | undefined;
ngOnInit() {
this.route.paramMap.pipe(
switchMap(params => this.productsService.getProduct(params.get('id')!)),
).subscribe(product => {
this.product = product;
});
}
}

Reading Params as a Signal

Modern Angular offers input binding for route params — declaring a matching input() automatically receives the param's value, no ActivatedRoute subscription required for the simple case.

// Requires withComponentInputBinding() passed to provideRouter()
export class ProductDetailComponent {
id = input<string>(); // automatically bound from the :id route param
}

Nested (Child) Routes

A route can define children, rendered through a nested router-outlet inside the parent route's own component template — directly mirroring nested layouts in other frameworks.

export const routes: Routes = [
{
path: 'dashboard',
component: DashboardLayoutComponent,
children: [
{ path: '', component: DashboardHomeComponent },
{ path: 'settings', component: DashboardSettingsComponent }, // → /dashboard/settings
],
},
];
// dashboard-layout.component.ts
@Component({
selector: 'app-dashboard-layout',
standalone: true,
imports: [RouterOutlet],
template: `
<aside>Sidebar</aside>
<router-outlet /> <!-- child route renders here -->
`,
})
export class DashboardLayoutComponent {}

Common Beginner Mistakes

Treating route params as numbers

Route params are always strings — convert them explicitly (Number(params.get('id'))) before using them in numeric comparisons.

Using ngOnInit alone, expecting it to catch subsequent param changes

ngOnInit runs once; subscribing to route.paramMap (an Observable) is what lets a reused component instance react to a param changing without a full re-mount.

FAQs

It gives a one-time snapshot of the current route's params, useful when you know the component will always be freshly created (never reused) for a param change.

No — children are configured as part of the same routes array via the children property, all provided once at the app level.

Summary

Dynamic params make routes data-driven, read reactively through ActivatedRoute (or bound directly as a component input), and nested routes let you build layouts incrementally. Next, you'll protect routes from unauthorized access with route guards.

Next Lesson →

Route Guards