Master Angular routing and navigation. Learn to configure routes, implement navigation, use route parameters, guards, and lazy loading.
Master Angular routing and navigation. Learn to configure routes, implement navigation, use route parameters, guards, and lazy loading.
In standalone applications (Angular 14+), router configuration is done in the bootstrap process:
1import { bootstrapApplication } from '@angular/platform-browser';
2import { provideRouter } from '@angular/router';
3import { routes } from './app/app.routes';
4import { AppComponent } from './app/app.component';
5
6bootstrapApplication(AppComponent, {
7 providers: [
8 provideRouter(routes)
9 ]
10});Learn about Defining Routes.
1// app.routes.ts
2import { Routes } from '@angular/router';
3import { HomeComponent } from './home/home.component';
4import { AboutComponent } from './about/about.component';
5import { ContactComponent } from './contact/contact.component';
6import { NotFoundComponent } from './not-found/not-found.component';
7
8export const routes: Routes = [
9 { path: '', component: HomeComponent },
10 { path: 'about', component: AboutComponent },
11 { path: 'contact', component: ContactComponent },
12 { path: '**', component: NotFoundComponent } // Wildcard route
13];The router-outlet directive marks where the router should display the routed components:
Learn about App Component with Router Outlet.
1import { Component } from '@angular/core';
2import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
3
4@Component({
5 selector: 'app-root',
6 standalone: true,
7 imports: [RouterOutlet, RouterLink, RouterLinkActive],
8 template: \`
9 <nav>
10 <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
11 Home
12 </a>
13 <a routerLink="/about" routerLinkActive="active">About</a>
14 <a routerLink="/contact" routerLinkActive="active">Contact</a>
15 </nav>
16
17 <main>
18 <router-outlet />
19 </main>
20 \`,
21 styles: [\`
22 nav {
23 display: flex;
24 gap: 16px;
25 padding: 20px;
26 background: #f8fafc;
27 }
28 a {
29 text-decoration: none;
30 color: #64748b;
31 padding: 8px 16px;
32 border-radius: 6px;
33 }
34 a.active {
35 background: #3b82f6;
36 color: white;
37 }
38 \`]
39})
40export class AppComponent {}Route parameters allow you to pass data through the URL:
Learn about Defining Parameterized Routes.
1export const routes: Routes = [
2 { path: 'users', component: UserListComponent },
3 { path: 'users/:id', component: UserDetailComponent },
4 { path: 'users/:id/edit', component: UserEditComponent }
5];Learn about Reading Route Parameters.
1import { Component, inject, OnInit } from '@angular/core';
2import { ActivatedRoute } from '@angular/router';
3
4@Component({
5 selector: 'app-user-detail',
6 standalone: true,
7 template: \`
8 <div>
9 <h2>User Details</h2>
10 <p>User ID: {{ userId }}</p>
11 </div>
12 \`
13})
14export class UserDetailComponent implements OnInit {
15 private route = inject(ActivatedRoute);
16 userId: string = '';
17
18 ngOnInit() {
19 // Using snapshot (for non-changing routes)
20 this.userId = this.route.snapshot.params['id'];
21
22 // Using observable (for changing routes)
23 this.route.params.subscribe(params => {
24 this.userId = params['id'];
25 this.loadUser(this.userId);
26 });
27 }
28
29 loadUser(id: string) {
30 console.log('Loading user:', id);
31 }
32}Navigate programmatically using the Router service:
1import { Component, inject } from '@angular/core';
2import { Router } from '@angular/router';
3
4@Component({
5 selector: 'app-login',
6 standalone: true,
7 template: \`
8 <button (click)="login()">Login</button>
9 \`
10})
11export class LoginComponent {
12 private router = inject(Router);
13
14 async login() {
15 // Perform login logic
16 const success = await this.authService.login();
17
18 if (success) {
19 // Navigate to dashboard
20 this.router.navigate(['/dashboard']);
21
22 // Navigate with parameters
23 this.router.navigate(['/users', userId]);
24
25 // Navigate with query params
26 this.router.navigate(['/search'], {
27 queryParams: { q: 'angular', page: 1 }
28 });
29
30 // Navigate with fragment
31 this.router.navigate(['/about'], {
32 fragment: 'section-2'
33 });
34 }
35 }
36}Route guards control navigation to and from routes:
Learn about Functional Guard (Angular 15+).
1import { inject } from '@angular/core';
2import { Router, CanActivateFn } from '@angular/router';
3import { AuthService } from './auth.service';
4
5export const authGuard: CanActivateFn = (route, state) => {
6 const authService = inject(AuthService);
7 const router = inject(Router);
8
9 if (authService.isLoggedIn()) {
10 return true;
11 }
12
13 // Redirect to login
14 return router.createUrlTree(['/login'], {
15 queryParams: { returnUrl: state.url }
16 });
17};
18
19// In routes
20export const routes: Routes = [
21 {
22 path: 'dashboard',
23 component: DashboardComponent,
24 canActivate: [authGuard]
25 }
26];Learn about CanDeactivate Guard.
1import { CanDeactivateFn } from '@angular/router';
2
3export interface CanComponentDeactivate {
4 canDeactivate: () => boolean | Observable<boolean>;
5}
6
7export const unsavedChangesGuard: CanDeactivateFn<CanComponentDeactivate> =
8 (component) => {
9 return component.canDeactivate ?
10 component.canDeactivate() :
11 true;
12 };
13
14// In component
15@Component({...})
16export class EditFormComponent implements CanComponentDeactivate {
17 hasUnsavedChanges = false;
18
19 canDeactivate(): boolean {
20 if (this.hasUnsavedChanges) {
21 return confirm('You have unsaved changes. Are you sure you want to leave?');
22 }
23 return true;
24 }
25}Lazy loading loads feature modules on demand, improving initial load time:
1export const routes: Routes = [
2 { path: '', component: HomeComponent },
3 {
4 path: 'admin',
5 loadChildren: () => import('./admin/admin.routes')
6 .then(m => m.ADMIN_ROUTES)
7 },
8 {
9 path: 'users',
10 loadComponent: () => import('./users/user-list.component')
11 .then(m => m.UserListComponent)
12 }
13];
14
15// admin.routes.ts
16export const ADMIN_ROUTES: Routes = [
17 { path: '', component: AdminDashboardComponent },
18 { path: 'users', component: AdminUsersComponent },
19 { path: 'settings', component: AdminSettingsComponent }
20];Child routes enable nested navigation within components:
1export const routes: Routes = [
2 {
3 path: 'products',
4 component: ProductsComponent,
5 children: [
6 { path: '', component: ProductListComponent },
7 { path: ':id', component: ProductDetailComponent },
8 { path: ':id/reviews', component: ProductReviewsComponent }
9 ]
10 }
11];
12
13// ProductsComponent template
14@Component({
15 template: \`
16 <div class="products-layout">
17 <aside>
18 <nav>Product Navigation</nav>
19 </aside>
20 <main>
21 <router-outlet />
22 </main>
23 </div>
24 \`
25})
26export class ProductsComponent {}Resolvers pre-fetch data before activating a route:
1import { inject } from '@angular/core';
2import { ResolveFn } from '@angular/router';
3import { UserService } from './user.service';
4
5export const userResolver: ResolveFn<User> = (route, state) => {
6 const userService = inject(UserService);
7 const userId = route.params['id'];
8 return userService.getUser(userId);
9};
10
11// In routes
12export const routes: Routes = [
13 {
14 path: 'users/:id',
15 component: UserDetailComponent,
16 resolve: {
17 user: userResolver
18 }
19 }
20];
21
22// In component
23@Component({...})
24export class UserDetailComponent implements OnInit {
25 private route = inject(ActivatedRoute);
26 user: User;
27
28 ngOnInit() {
29 this.user = this.route.snapshot.data['user'];
30 }
31}Use lazy loading for large feature modules to improve initial load time
Implement route guards for authentication and authorization
Use resolvers to pre-load data and avoid loading states in components
Always include a wildcard route (**) for 404 pages
Use routerLinkActive for highlighting active navigation links
Subscribe to route params observable for routes that can navigate to themselves
Use child routes for complex nested layouts
Implement preloading strategies for better user experience
Use functional guards (Angular 15+) for cleaner, more testable code
Angular Router enables single-page application navigation with full browser history support
Routes are configured as an array of route definitions with paths and components
RouterLink directive provides declarative navigation, Router service provides programmatic navigation
Route parameters allow passing dynamic data through the URL
Route guards control access to routes based on conditions like authentication
Lazy loading splits the application into chunks loaded on demand
Child routes enable nested navigation within parent components
Route resolvers pre-fetch data before activating routes
Wildcard routes (**) handle undefined routes for 404 pages
Your progress is saved in this browser, on this device only.