Angular Routing & Navigation
What is Routing in Angular?
Routing is the mechanism that allows an Angular application to display different components based on the current URL in the browser. Without routing, the application would always show the same content regardless of the URL. With routing, navigating to /home shows the home component, navigating to /products shows the products component, and so on — all without reloading the page.
Angular's routing is handled by the Angular Router, a built-in module that maps URL paths to components. The router updates the browser's address bar and manages the browser's history (back/forward navigation) automatically.
Setting Up Routing
When creating a project with ng new and choosing "Yes" for routing, Angular automatically creates an AppRoutingModule. This file is where all routes are defined.
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { ProductsComponent } from './pages/products/products.component';
import { AboutComponent } from './pages/about/about.component';
import { NotFoundComponent } from './pages/not-found/not-found.component';
const routes: Routes = [
{ path: '', component: HomeComponent }, // Default route (/)
{ path: 'products', component: ProductsComponent }, // /products
{ path: 'about', component: AboutComponent }, // /about
{ path: '**', component: NotFoundComponent } // Catch-all (404 page)
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Understanding the Routes Array
Each object in the routes array is a route definition with at minimum two properties:
path— The URL segment that activates this route. An empty string''matches the root URL.component— The component to display when this path matches.
The ** path is a wildcard — it matches any URL that did not match the routes above it. This is used for 404 "Page Not Found" pages. Routes are evaluated top to bottom, so the wildcard must always be the last route.
The router-outlet Tag
The <router-outlet> tag is a placeholder in the main application template where the router renders the matched component. Place it in app.component.html:
<!-- app.component.html -->
<nav>
<a routerLink="/">Home</a>
<a routerLink="/products">Products</a>
<a routerLink="/about">About</a>
</nav>
<router-outlet></router-outlet>
<!-- The matched component renders here -->
When the user clicks "Products", the URL changes to /products, and the router replaces the content inside <router-outlet> with the ProductsComponent — without reloading the page.
The routerLink Directive
routerLink is the Angular equivalent of a standard HTML href attribute. Unlike href, which triggers a full page reload, routerLink uses Angular's router to navigate without reloading, keeping the application fast.
<!-- Static routes -->
<a routerLink="/">Home</a>
<a routerLink="/products">Products</a>
<a routerLink="/about">About</a>
<!-- Dynamic routes using array syntax -->
<a [routerLink]="['/products', product.id]">View Product</a>
<!-- Navigates to /products/5 if product.id is 5 -->
Active Route Styling with routerLinkActive
The routerLinkActive directive adds a CSS class to a link when its route is currently active. This is used to visually highlight the current page in the navigation:
<nav>
<a routerLink="/" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">Home</a>
<a routerLink="/products" routerLinkActive="active-link">Products</a>
<a routerLink="/about" routerLinkActive="active-link">About</a>
</nav>
The exact: true option ensures the home link only highlights when the URL is exactly /, not when it contains / as part of any other path.
Route Parameters — Dynamic Routes
Route parameters allow creating dynamic routes where part of the URL carries data. For example, /products/5 would show the product with ID 5.
Defining a Route with a Parameter
const routes: Routes = [
{ path: 'products', component: ProductsComponent },
{ path: 'products/:id', component: ProductDetailComponent }, // :id is the parameter
{ path: 'blog/:year/:month/:slug', component: BlogPostComponent } // Multiple parameters
];
Reading the Route Parameter in a Component
// product-detail.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-product-detail',
templateUrl: './product-detail.component.html'
})
export class ProductDetailComponent implements OnInit {
productId: string = '';
product: any = null;
private allProducts = [
{ id: '1', name: 'Laptop Stand', price: 39.99 },
{ id: '2', name: 'Wireless Mouse', price: 24.99 },
{ id: '3', name: 'USB-C Hub', price: 45.00 }
];
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// Read the 'id' parameter from the URL
this.productId = this.route.snapshot.paramMap.get('id') || '';
this.product = this.allProducts.find(p => p.id === this.productId);
}
}
<!-- product-detail.component.html -->
<div *ngIf="product; else notFound">
<h2>{{ product.name }}</h2>
<p>Price: {{ product.price | currency }}</p>
<a routerLink="/products">← Back to Products</a>
</div>
<ng-template #notFound>
<p>Product not found.</p>
</ng-template>
Query Parameters
Query parameters are key-value pairs added to the URL after a ?. They are used for optional data like search terms, filters, or page numbers. Example URL: /products?category=accessories&page=2
Navigating with Query Parameters
<a [routerLink]="['/products']" [queryParams]="{ category: 'accessories', page: 1 }">
View Accessories
</a>
Reading Query Parameters
// products.component.ts
import { ActivatedRoute } from '@angular/router';
export class ProductsComponent implements OnInit {
category = '';
page = 1;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.queryParamMap.subscribe(params => {
this.category = params.get('category') || '';
this.page = Number(params.get('page')) || 1;
});
}
}
Programmatic Navigation
Navigation can also be triggered from TypeScript code using the Router service. This is useful for redirecting after form submissions or login events.
// login.component.ts
import { Router } from '@angular/router';
export class LoginComponent {
constructor(private router: Router) {}
onLogin(username: string, password: string) {
if (username === 'admin' && password === '1234') {
// Navigate to dashboard after successful login
this.router.navigate(['/dashboard']);
} else {
// Navigate to error page with query param
this.router.navigate(['/login'], { queryParams: { error: 'invalid' } });
}
}
}
Child Routes (Nested Routes)
Child routes define sub-pages within a parent route. For example, a settings page at /settings might have sub-pages at /settings/profile and /settings/security.
const routes: Routes = [
{
path: 'settings',
component: SettingsComponent,
children: [
{ path: '', redirectTo: 'profile', pathMatch: 'full' },
{ path: 'profile', component: ProfileComponent },
{ path: 'security', component: SecurityComponent },
{ path: 'notifications', component: NotificationsComponent }
]
}
];
The parent SettingsComponent template must include a <router-outlet> for the child routes to render inside:
<!-- settings.component.html -->
<h2>Settings</h2>
<nav>
<a routerLink="profile">Profile</a>
<a routerLink="security">Security</a>
<a routerLink="notifications">Notifications</a>
</nav>
<router-outlet></router-outlet>
Redirects
A redirect sends the user from one route to another automatically:
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' }, // Redirect root to /home
{ path: 'home', component: HomeComponent },
{ path: 'old-page', redirectTo: '/new-page' }, // Redirect old URL to new URL
{ path: 'new-page', component: NewPageComponent }
];
pathMatch: 'full' means the redirect only applies when the entire URL matches the empty path — not just when it starts with an empty string.
Summary
Angular routing maps URL paths to components, enabling navigation without page reloads. Routes are defined in AppRoutingModule as an array of path-component pairs. The <router-outlet> tag is the placeholder where matched components render. The routerLink directive replaces standard href for internal navigation. Route parameters (:id) create dynamic URLs, read using ActivatedRoute. Query parameters carry optional data in the URL. Programmatic navigation uses the Router service's navigate() method. Child routes enable nested page hierarchies. Wildcard routes (**) catch unmatched URLs for 404 handling.
