Angular Tutorial menu

Angular Routing

Routing lets one Angular app show different pages for different URLs, without reloading the browser.

How Routing Works

An Angular app has one HTML page. The router watches the URL in the address bar and shows the matching component inside a placeholder called <router-outlet>.

URLComponent shown
/Home
/coursesCourses
/courses/3CourseDetail for course 3
/contactContact

Step 1: Define the Routes

New projects already have src/app/app.routes.ts. Add your routes:

Example

typescript
import { Routes } from "@angular/router";
import { Home } from "./home/home";
import { Courses } from "./courses/courses";
import { CourseDetail } from "./course-detail/course-detail";
import { Contact } from "./contact/contact";
import { NotFound } from "./not-found/not-found";

export const routes: Routes = [
  { path: "", component: Home, title: "Home" },
  { path: "courses", component: Courses, title: "Our Courses" },
  { path: "courses/:id", component: CourseDetail },
  { path: "contact", component: Contact, title: "Contact Us" },
  { path: "**", component: NotFound },
];
  • path is the URL without the leading slash. "" is the home page
  • :id is a route parameter, a changing part of the URL
  • title sets the browser tab title
  • "**" matches any URL not listed above, for a "page not found" screen. Keep it last

Step 2: Provide the Router

src/app/app.config.ts connects the routes to the app:

Example

typescript
import { ApplicationConfig } from "@angular/core";
import { provideRouter } from "@angular/router";
import { routes } from "./app.routes";

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes)],
};

In the root component, add navigation links and the outlet:

Example

typescript
import { Component } from "@angular/core";
import { RouterOutlet, RouterLink, RouterLinkActive } from "@angular/router";

@Component({
  selector: "app-root",
  imports: [RouterOutlet, RouterLink, RouterLinkActive],
  template: `
    <nav>
      <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a>
      <a routerLink="/courses" routerLinkActive="active">Courses</a>
      <a routerLink="/contact" routerLinkActive="active">Contact</a>
    </nav>

    <router-outlet />
  `,
})
export class App {}
  • routerLink changes the page without a full reload. Do not use href for internal links
  • routerLinkActive adds a CSS class to the link of the current page
  • <router-outlet /> is where the page component appears

Reading a Route Parameter

The easiest way is to turn on component input binding, so route parameters arrive as inputs:

Example

typescript
provideRouter(routes, withComponentInputBinding())

(import withComponentInputBinding from @angular/router). Then in CourseDetail:

Example

typescript
import { Component, input, computed } from "@angular/core";

const COURSES = [
  { id: "1", name: "Web Development" },
  { id: "2", name: "Graphic Designing" },
  { id: "3", name: "Artificial Intelligence" },
];

@Component({
  selector: "app-course-detail",
  template: `
    @if (course(); as c) {
      <h2>{{ c.name }}</h2>
    } @else {
      <p>Course not found.</p>
    }
  `,
})
export class CourseDetail {
  id = input.required<string>();
  course = computed(() => COURSES.find((c) => c.id === this.id()));
}

Visiting /courses/3 shows:

Output
Artificial Intelligence

Route parameters are always strings, so compare them with strings or convert them with Number().

Example

html
@for (c of courses; track c.id) {
  <a [routerLink]="['/courses', c.id]">{{ c.name }}</a>
}

After a form is saved, you may want to move to another page:

Example

typescript
import { Component, inject } from "@angular/core";
import { Router } from "@angular/router";

@Component({
  selector: "app-contact",
  template: `<button (click)="send()">Send message</button>`,
})
export class Contact {
  private router = inject(Router);

  send() {
    // ...save the message...
    this.router.navigate(["/"]);
  }
}

For big apps, load pages only when needed with loadComponent: () => import("./admin/admin").then((m) => m.Admin). This is called lazy loading and makes the first page load faster.

Exercise

Exercise

Where does the router display the component for the current URL?

Learn Angular with a teacher

Join the Full Stack Development course at Workownix, online or in Orangi Town, Karachi, and get a certificate.

See the course Ask on WhatsApp