← Back to Tutorials Chapter 8

Routing

What is Angular Routing?

The Angular Router enables navigation between different views or components in a single-page application. It interprets browser URLs and maps them to the corresponding component views. The router supports deep linking, lazy loading, guards, resolvers, and nested routes.

RouterModule.forRoot

Configure the router at the application root level using RouterModule.forRoot in the root module (or provideRouter for standalone apps):

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

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'products', component: ProductListComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
Use RouterModule.forChild(routes) in feature modules to register child routes without re-creating the router service.

Route Configuration

Each route is an object with several properties:

const routes: Routes = [
  { path: '', component: HomeComponent, pathMatch: 'full' },
  { path: 'products', component: ProductListComponent },
  { path: 'products/:id', component: ProductDetailComponent },
  { path: 'category/:categoryName', component: CategoryComponent },
  { path: '**', component: NotFoundComponent }  // Wildcard — must be last
];

redirectTo

Redirect from one path to another:

{ path: 'old-products', redirectTo: '/products', pathMatch: 'full' }

Wildcard Route (**)

Catches all unmatched routes — typically used for a 404 page. Must be defined last in the routes array.

Parameterized Routes (:id)

Pass dynamic values via the URL path:

// Route config
{ path: 'users/:userId', component: UserDetailComponent }

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

ngOnInit() {
  this.route.params.subscribe(params => {
    this.userId = params['userId'];
    this.loadUser();
  });
}

Query Parameters and Fragments

Access query parameters (?page=1&sort=name) and fragments (#section):

// Reading
this.route.queryParams.subscribe(params => {
  this.page = params['page'];
});
this.route.fragment.subscribe(f => this.section = f);

// Navigation
this.router.navigate(['/products'], {
  queryParams: { page: 2, sort: 'price' },
  fragment: 'reviews'
});

Nested Routes (Children)

Create hierarchies of routes with child components:

const routes: Routes = [
  {
    path: 'dashboard',
    component: DashboardComponent,
    children: [
      { path: '', redirectTo: 'overview', pathMatch: 'full' },
      { path: 'overview', component: OverviewComponent },
      { path: 'analytics', component: AnalyticsComponent },
      { path: 'settings', component: SettingsComponent }
    ]
  }
];

The parent component must include a <router-outlet> to render child routes.

routerLink and routerLinkActive

Navigate using declarative links in templates:

<nav>
  <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
  <a routerLink="/products" routerLinkActive="active"
     [routerLinkActiveOptions]="{ exact: false }">Products</a>
  <a [routerLink]="['/users', user.id]">User Profile</a>
</nav>

routerLinkActive adds a CSS class (e.g., active) when the current URL matches the link. Use exact: true for exact path matching.

Router.navigate (Programmatic Navigation)

Navigate imperatively in your component class:

constructor(private router: Router) { }

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

goToDashboard() {
  this.router.navigateByUrl('/dashboard');
}

Route Guards

Protect routes with guards. Common guard types: CanActivate, CanActivateChild, CanDeactivate, Resolve, and CanLoad.

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

@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  constructor(private auth: AuthService, private router: Router) { }

  canActivate(): boolean {
    if (this.auth.isLoggedIn()) return true;
    this.router.navigate(['/login']);
    return false;
  }
}

// Route config
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }

Lazy Loading with loadChildren

Load feature modules on demand to reduce initial bundle size:

{
  path: 'admin',
  loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}

Angular splits the admin module into a separate chunk, loaded only when the user navigates to /admin.

Angular routing flow diagram

Summary

This chapter covered the Angular Router: route configuration, parameterized routes, query parameters and fragments, nested routes, routerLink and routerLinkActive, programmatic navigation, route guards (CanActivate), and lazy loading with loadChildren. With these tools, you can build complex navigation flows for SPAs.

Exercise 8: Set up routes for an e-commerce app with Home, Products (lazy-loaded), Product Detail (with :id), Cart, and Checkout pages. Add a CanActivate guard that redirects unauthenticated users from the Checkout page to a Login page. Add a 404 wildcard route. Use routerLinkActive to highlight the active nav item. Use query params for product filtering (?category=electronics&sort=price).