Routing
The Angular Router turns your app into many “pages” with real URLs — /products, /cart, /account — while still being a single-page app that never fully reloads.
On this page · 6 min · Intermediate
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 6 min
- Difficulty
- Intermediate
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Define routes and register them with provideRouter
- Show pages with <router-outlet>
- Link with routerLink and highlight with routerLinkActive
- Redirect, handle 404s and navigate from code
Explanation#
A route maps a path to a component: { path: "products", component: ProductList }. The table lives in app.routes.ts and is registered with provideRouter(routes) in app.config.ts.
<router-outlet /> in the root template marks where the current page appears. Everything outside it (header, sidebar) stays on screen.
routerLink="/products" navigates without reloading; routerLinkActive="active" adds a class to the link of the current page. Import RouterLink, RouterLinkActive and RouterOutlet.
{ path: "", redirectTo: "home", pathMatch: "full" } redirects; { path: "**", component: NotFound } catches unknown URLs and must come last.
Navigate from code with inject(Router).navigate(["/orders", id]) or navigateByUrl("/cart") — for example after saving a form.
Set page titles per route with the title property: { path: "cart", component: Cart, title: "Your cart" }.
Syntax#
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: Home, title: 'Home' },
{ path: 'products', component: ProductList, title: 'Products' },
{ path: '**', component: NotFound },
];
Code example: A shop shell with three pages and a 404#
import { Component, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { Router, RouterLink, RouterLinkActive, RouterOutlet, Routes, provideRouter } from '@angular/router';
@Component({ selector: 'app-home', template: `<h1>Welcome</h1>` })
export class Home {}
@Component({ selector: 'app-products', template: `<h1>Products</h1><p>Pen · Notebook · Bag</p>` })
export class Products {}
@Component({
selector: 'app-cart',
template: `<h1>Cart</h1><button (click)="checkout()">Checkout</button>`,
})
export class Cart {
private router = inject(Router);
checkout() {
this.router.navigate(['/home'], { queryParams: { ordered: 1 } }); // navigate from code
}
}
@Component({ selector: 'app-not-found', imports: [RouterLink], template: `<h1>404</h1><a routerLink="/home">Go home</a>` })
export class NotFound {}
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: Home, title: 'Home | Shop' },
{ path: 'products', component: Products, title: 'Products | Shop' },
{ path: 'cart', component: Cart, title: 'Cart | Shop' },
{ path: '**', component: NotFound, title: 'Not found' },
];
@Component({
selector: 'app-root',
imports: [RouterOutlet, RouterLink, RouterLinkActive],
template: `
<nav>
<a routerLink="/home" routerLinkActive="active">Home</a> |
<a routerLink="/products" routerLinkActive="active">Products</a> |
<a routerLink="/cart" routerLinkActive="active">Cart</a>
</nav>
<router-outlet />
`,
styles: `.active { font-weight: bold; text-decoration: underline; }`,
})
export class App {}
bootstrapApplication(App, { providers: [provideRouter(routes)] });
Opening “/” redirects to /home (“Welcome”). Clicking Products or Cart changes the URL and the page below the nav without a reload; the current link is bold and underlined and the browser tab title changes. “Checkout” navigates to /home?ordered=1. Any unknown URL such as /xyz shows the 404 page.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- Routes map paths to components; the empty path redirects to home.
- provideRouter(routes) registers the router when the app starts.
- <router-outlet /> shows the active page; the nav stays in place.
- routerLinkActive adds the active class to the current link.
- Cart navigates from code with Router.navigate and query parameters.
- The ** route catches everything else and must be last.
Real-world use case#
A banking portal has /accounts, /transfers, /cards and /profile under one shell with a sidebar. Bookmarks and the browser’s back button work like a traditional website.
Common mistakes#
<a href="/products"> reloads the entire app. Use routerLink.
Routes are matched in order; ** first catches everything. Put it last.
With prefix matching, every URL matches "", causing redirect loops.
Best practices#
- Routes in app.routes.ts, provideRouter in app.config.ts
- routerLink + routerLinkActive for navigation
- Titles per route
- A catch-all 404 route last
Remember this#
Route = path → component.
<router-outlet /> = where pages appear.
routerLink, not href. ** route goes last.
Practice exercise#
Your task: Add a route "contact" with title "Contact us" and a link in the nav that is bold when active.
Need a hint?
Show solution
import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive, Routes } from '@angular/router';
@Component({ selector: 'app-contact', template: `<h1>Contact us</h1>` })
export class Contact {}
export const routes: Routes = [
{ path: 'contact', component: Contact, title: 'Contact us' },
// … other routes, then { path: '**', … } last
];
@Component({
selector: 'app-nav',
imports: [RouterLink, RouterLinkActive],
template: `<a routerLink="/contact" routerLinkActive="active">Contact</a>`,
styles: `.active { font-weight: bold; }`,
})
export class Nav {}
Mini quiz#
Where does the routed component appear?
Want more? Practise all Angular MCQs · Angular interview questions
My notes#
Saved in this browser.