Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Angular Router


The Router maps URLs to views and lets users navigate your app.


Router Essentials

  • URL-driven UI: The Router swaps views based on the URL.
  • RouterOutlet: Placeholder where the active route's component renders.
  • routerLink: Navigate without full page reloads.
  • RouterLinkActive: Adds classes to active links (use { exact: true } for root).
  • Performance & control: Lazy load feature areas; use guards to allow/block navigation.
import { provideRouter, withHashLocation, RouterOutlet, RouterLink } from '@angular/router';

const routes = [
  { path: '', component: Home },
  { path: 'about', component: About }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});

// Template
// <a routerLink="/about">About</a>
// <router-outlet></router-outlet>

Notes:

  • Related: See Components for building views, Services for shared logic/guards, and Templates for markup and directives.
  • Standalone apps: import RouterOutlet/RouterLink and provide routes with provideRouter().
  • Sandboxes/runners: use withHashLocation() so links work without server config (hash URLs look like /#/path).

Router Basics

  • Define a routes array that maps paths to components.
  • Provide routes with provideRouter() (use withHashLocation() for sandboxes).
  • Use routerLink for navigation and RouterOutlet to render views.
const routes = [ { path: '', component: Home }, { path: 'about', component: About } ];
// template
// <a routerLink="/about">About</a>
// <router-outlet></router-outlet>

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { provideRouter, RouterOutlet, RouterLink, withHashLocation } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink],
  template: `
    <h3>Router</h3>
    <nav>
      <a routerLink="/">Home</a> |
      <a routerLink="/about">About</a>
    </nav>
    <router-outlet></router-outlet>
  `
})
export class App {}

@Component({
  standalone: true,
  template: `<p>Home works!</p>`
})
export class Home {}

@Component({
  standalone: true,
  template: `<p>About works!</p>`
})
export class About {}

const routes = [
  { path: '', component: Home },
  { path: 'about', component: About }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});
<app-root></app-root>

Run Example »

Example explained

  • provideRouter(routes): Registers the routes for the app.
  • RouterOutlet: Placeholder where the active route's component renders.
  • routerLink: Navigates without reloading the page.
  • withHashLocation(): Uses hash URLs so links work in sandboxes without server rewrites.

Notes:

  • Use routerLink, not href: href reloads the page.
  • Use routerLink for SPA navigation.
  • Standalone imports: Import RouterOutlet/RouterLink and provide routes with provideRouter().

REMOVE ADS


Router Params

  • Capture variables in paths with :id (e.g., /product/42).
  • Read them via ActivatedRoute (snapshot or paramMap observable).
{ path: 'product/:id', component: Product }
// class Product {
//  id = '';
//  route = inject(ActivatedRoute);
//  ngOnInit() { this.id = this.route.snapshot.paramMap.get('id') ?? ''; }
// }

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, OnInit, inject } from '@angular/core';
import { provideRouter, RouterOutlet, RouterLink, RouterLinkActive, ActivatedRoute, withHashLocation } from '@angular/router';

@Component({
  selector: 'home-cmp',
  standalone: true,
  template: `<p>Home works!</p>`
})
export class Home {}

@Component({
  selector: 'product-cmp',
  standalone: true,
  template: `<p>Product ID: {{ id }}</p>`
})
export class Product implements OnInit {
  id = '';
  private route = inject(ActivatedRoute);
  ngOnInit() {
    this.id = this.route.snapshot.paramMap.get('id') ?? '';
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink, RouterLinkActive],
  template: `
    <h3>Router Params</h3>
    <nav>
      <a routerLink="/">Home</a> |
      <a routerLink="/product/1" routerLinkActive="active">Product 1</a> |
      <a routerLink="/product/2" routerLinkActive="active">Product 2</a>
    </nav>
    <router-outlet></router-outlet>
  `,
  styles: [`nav a { margin-right: 6px; } .active { font-weight: bold; }`]
})
export class App {}

const routes = [
  { path: '', component: Home },
  { path: 'product/:id', component: Product }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});
<app-root></app-root>

Run Example »

Example explained

  • product/:id: Declares a path parameter named id.
  • ActivatedRoute: Reads id from snapshot.paramMap.get('id') in ngOnInit.
  • Links: routerLink="/product/1" and /product/2 demonstrate parameterized navigation.

Params update within the same component: If navigating to the same route with different params, subscribe to paramMap (or params) instead of using a one-time snapshot.


Active Links

  • Use routerLinkActive to toggle classes when a link matches.
  • Set { exact: true } for root links like /.
<a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a>
<a routerLink="/about" routerLinkActive="active">About</a>

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { provideRouter, RouterOutlet, RouterLink, RouterLinkActive, withHashLocation } from '@angular/router';

@Component({
  standalone: true,
  template: `<p>Home works!</p>`
})
export class Home {}

@Component({
  standalone: true,
  template: `<p>About works!</p>`
})
export class About {}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink, RouterLinkActive],
  styles: [`
    nav a { margin-right: 8px; text-decoration: none; }
    .active { font-weight: 600; color: seagreen; }
  `],
  template: `
    <h3>Active Links (routerLinkActive)</h3>
    <nav>
      <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a>
      <a routerLink="/about" routerLinkActive="active">About</a>
    </nav>
    <router-outlet></router-outlet>
  `
})
export class App {}

const routes = [
  { path: '', component: Home },
  { path: 'about', component: About }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});
<app-root></app-root>

Run Example »

Example explained

  • routerLinkActive="active": Adds the active class when the link matches the current URL.
  • [routerLinkActiveOptions]="{ exact: true }": For the root (/), only mark active on exact match.
  • RouterOutlet: Renders the matched component for the current route.

Notes:

  • Exact for root: For / links, set { exact: true } so parent paths don't keep them active.
  • Apply on containers: Put routerLinkActive on a parent element to style groups of links.
  • Multiple classes: You can add several classes: routerLinkActive="active bold".

Lazy-loaded Component

  • Defer loading code until navigation with loadComponent or loadChildren.
  • Improves initial load time by splitting bundles.
{ path: 'about', loadComponent: () => import('./about').then(m => m.About) }

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component } from '@angular/core';
import { provideRouter, RouterOutlet, RouterLink, withHashLocation } from '@angular/router';

@Component({
  standalone: true,
  template: `<p>Home works!</p>`
})
export class Home {}

@Component({
  standalone: true,
  template: `<p>About works (lazy)!</p>`
})
export class About {}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink],
  styles: [`
    nav a { margin-right: 8px; text-decoration: none; }
  `],
  template: `
    <h3>Lazy-loaded Component (loadComponent)</h3>
    <nav>
      <a routerLink="/">Home</a>
      <a routerLink="/about">About (lazy)</a>
    </nav>
    <router-outlet></router-outlet>
  `
})
export class App {}

const routes = [
  { path: '', component: Home },
  // Use Promise.resolve to simulate lazy loading without dynamic imports
  { path: 'about', loadComponent: () => Promise.resolve(About) }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});
<app-root></app-root>

Run Example »

Example explained

  • loadComponent: Defers loading the route's component until navigation (here simulated with Promise.resolve).
  • Routes: Home is eager; About is lazy.
  • Navigation: Clicking “About (lazy)” loads and renders the component on demand.

Notes:

  • Route order and wildcards: Put catch-all routes last so they don't swallow other routes.
  • Deep-link refreshes: Without server rewrites, refreshes may 404.
  • In demos/sandboxes use withHashLocation().

Route Guard (canActivate)

  • Guards decide if navigation is allowed.
  • Return true (allow), false/UrlTree (block/redirect), or async equivalents.
export const authGuard = () => isLoggedIn ? true : inject(Router).createUrlTree(['/']);
{ path: 'protected', component: Protected, canActivate: [authGuard] }

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { provideRouter, RouterOutlet, RouterLink, withHashLocation, Router } from '@angular/router';

let loggedIn = false;

export const authGuard = () => {
  if (loggedIn) return true;
  const router = inject(Router);
  return router.createUrlTree(['/']);
};

@Component({
  standalone: true,
  template: `<p>Home (public).</p>
<p>Login to access protected route.</p>`
})
export class Home {}

@Component({
  standalone: true,
  template: `<p>Protected works! You are logged in.</p>`
})
export class Protected {}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, RouterLink],
  styles: [`
    nav a { margin-right: 8px; text-decoration: none; }
    .status { margin-left: 8px; font-weight: 600; }
  `],
  template: `
    <h3>Route Guard (canActivate)</h3>
    <div class="toolbar">
      <button (click)="toggle()">{{ loggedIn ? 'Log out' : 'Log in' }}</button>
      <span class="status">Status: {{ loggedIn ? 'Logged in' : 'Logged out' }}</span>
    </div>
    <nav>
      <a routerLink="/">Home</a>
      <a routerLink="/protected">Protected</a>
    </nav>
    <router-outlet></router-outlet>
  `
})
export class App {
  get loggedIn() { return loggedIn; }
  toggle() { loggedIn = !loggedIn; }
}

const routes = [
  { path: '', component: Home },
  { path: 'protected', component: Protected, canActivate: [authGuard] }
];

bootstrapApplication(App, {
  providers: [provideRouter(routes, withHashLocation())]
});
<app-root></app-root>

Run Example »

Example explained

  • authGuard: Returns true when logged in; otherwise returns a UrlTree that redirects to /.
  • inject(Router): Accesses the Router to create a redirect UrlTree inside the guard function.
  • canActivate: Applies the guard to the /protected route.
  • Toggle: The button flips the loggedIn state to test both branches.

Guard return types: Return boolean, UrlTree, or an observable/promise of those.



×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.