Skip to main content

Angular Routing Basics

When building modern web applications with Angular, one of the most important features is the ability to navigate between different views without refreshing the entire page. This is where Angular's routing system comes in — it allows you to create Single Page Applications (SPAs) with multiple views that feel like traditional multi-page websites.

What is Angular Routing?

Angular Routing is a mechanism that allows you to define different navigation paths in your application. It enables users to move between different components (or "pages") in your application while maintaining the SPA experience. The Angular Router interprets the browser URL as an instruction to navigate to a client-generated view, allowing you to:

  • Navigate between different views
  • Pass data between routes
  • Protect routes with guards
  • Load components lazily for better performance

Getting Started with Angular Routing

Step 1: Set Up a Project with Routing

When you create a new Angular project, you can include routing from the beginning:

bash
ng new my-routing-app --routing

This command creates a new project with an AppRoutingModule already configured.

If you're adding routing to an existing project, you can generate a routing module:

bash
ng generate module app-routing --flat --module=app

Step 2: Understanding the Routing Module

Let's look at a basic app-routing.module.ts file:

typescript
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';

const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'contact', component: ContactComponent },
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: '**', redirectTo: '/home' } // Wildcard route for a 404 page
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

This module defines several routes:

  • /home shows the HomeComponent
  • /about shows the AboutComponent
  • /contact shows the ContactComponent
  • An empty path redirects to /home
  • A wildcard path (**) catches any undefined routes and redirects to /home

Step 3: Add the Router Outlet

To display routed components in your application, you need to add a router-outlet directive to your main app component template:

html
<!-- app.component.html -->
<header>
<nav>
<ul>
<li><a routerLink="/home" routerLinkActive="active">Home</a></li>
<li><a routerLink="/about" routerLinkActive="active">About</a></li>
<li><a routerLink="/contact" routerLinkActive="active">Contact</a></li>
</ul>
</nav>
</header>

<main>
<router-outlet></router-outlet>
</main>

<footer>
<p>© 2023 My Routing App</p>
</footer>

The <router-outlet> acts as a placeholder where the router displays the component for the current route.

The routerLink directive is used to create links that navigate to routes. Unlike regular href links, routerLink prevents page reloads and uses Angular's router instead.

html
<a routerLink="/about">About</a>

Active Route Styling

You can style the active route links using the routerLinkActive directive:

html
<a routerLink="/about" routerLinkActive="active-link">About</a>

Then in your CSS, you can define the styles for the active link:

css
.active-link {
color: #3f51b5;
font-weight: bold;
border-bottom: 2px solid #3f51b5;
}

Route Parameters

Routes often need to carry dynamic data. For example, in a product listing application, you might want to navigate to details for a specific product.

Defining a Route with Parameters

typescript
const routes: Routes = [
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent },
// other routes...
];

Linking to a Route with Parameters

html
<a [routerLink]="['/products', product.id]">View {{ product.name }}</a>

Accessing Route Parameters in a Component

typescript
import { ActivatedRoute } from '@angular/router';

@Component({
selector: 'app-product-detail',
templateUrl: './product-detail.component.html'
})
export class ProductDetailComponent implements OnInit {
productId: string;

constructor(private route: ActivatedRoute) { }

ngOnInit() {
// Access the route parameter as a snapshot
this.productId = this.route.snapshot.paramMap.get('id');

// Or subscribe to parameter changes (better for reusing the same component with different parameters)
this.route.paramMap.subscribe(params => {
this.productId = params.get('id');
// Load product data based on the ID
});
}
}

Programmatic Navigation

Besides using routerLink for declarative navigation in templates, you can also navigate programmatically from your component code:

typescript
import { Router } from '@angular/router';

@Component({
selector: 'app-login',
template: `
<form (ngSubmit)="onSubmit()">
<!-- form fields -->
<button type="submit">Login</button>
</form>
`
})
export class LoginComponent {
constructor(private router: Router) { }

onSubmit() {
// Authenticate user...

// After successful login, navigate to the dashboard
this.router.navigate(['/dashboard']);

// Or navigate with parameters
this.router.navigate(['/users', userId]);
}
}

Query Parameters and Fragments

Query parameters are an important part of URL structure. You can include them in your navigation.

html
<a [routerLink]="['/products']" [queryParams]="{category: 'electronics', sort: 'price'}">
Electronic Products
</a>

This will generate a URL like: /products?category=electronics&sort=price

Programmatically Adding Query Parameters

typescript
// Navigate with query parameters
this.router.navigate(['/products'], {
queryParams: { category: 'electronics', sort: 'price' }
});

// Preserve existing query parameters
this.router.navigate(['/products'], {
queryParams: { category: 'electronics' },
queryParamsHandling: 'merge' // or 'preserve'
});

Accessing Query Parameters

typescript
import { ActivatedRoute } from '@angular/router';

@Component({
// ...
})
export class ProductListComponent implements OnInit {
constructor(private route: ActivatedRoute) { }

ngOnInit() {
// Get query parameters as snapshot
const category = this.route.snapshot.queryParamMap.get('category');

// Or subscribe to query parameter changes
this.route.queryParamMap.subscribe(params => {
const category = params.get('category');
const sort = params.get('sort');
// Update component based on query params
});
}
}

URL Fragments

URL fragments (the part after # in a URL) are also supported in Angular routing.

html
<a [routerLink]="['/article/123']" fragment="comments">Jump to Comments</a>

This generates: /article/123#comments

Real-World Example: Building a Blog Application

Let's see how routing would be implemented in a simple blog application:

1. Define your routes

typescript
// app-routing.module.ts
const routes: Routes = [
{ path: '', component: BlogHomeComponent },
{ path: 'posts', component: PostListComponent },
{ path: 'posts/:id', component: PostDetailComponent },
{ path: 'categories/:category', component: CategoryPostsComponent },
{ path: 'about', component: AboutComponent },
{ path: 'contact', component: ContactComponent },
{ path: '**', component: PageNotFoundComponent }
];

2. Create navigation menu

html
<!-- app.component.html -->
<header>
<nav class="main-nav">
<a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Home</a>
<a routerLink="/posts" routerLinkActive="active">All Posts</a>
<a routerLink="/categories/technology" routerLinkActive="active">Technology</a>
<a routerLink="/categories/lifestyle" routerLinkActive="active">Lifestyle</a>
<a routerLink="/about" routerLinkActive="active">About</a>
<a routerLink="/contact" routerLinkActive="active">Contact</a>
</nav>
</header>

<main>
<router-outlet></router-outlet>
</main>

3. Create a post list page that links to individual posts

html
<!-- post-list.component.html -->
<h1>Blog Posts</h1>

<div class="post-filters">
<select (change)="onSortChange($event)">
<option value="newest">Newest First</option>
<option value="oldest">Oldest First</option>
</select>
</div>

<div class="post-list">
<article *ngFor="let post of posts">
<h2><a [routerLink]="['/posts', post.id]">{{ post.title }}</a></h2>
<p class="date">{{ post.date | date }}</p>
<p class="excerpt">{{ post.excerpt }}</p>
<a [routerLink]="['/posts', post.id]" class="read-more">Read more</a>
</article>
</div>

4. Create a post detail component that reads the route parameter

typescript
// post-detail.component.ts
@Component({
selector: 'app-post-detail',
templateUrl: './post-detail.component.html'
})
export class PostDetailComponent implements OnInit {
post: any;
loading = true;
error = false;

constructor(
private route: ActivatedRoute,
private blogService: BlogService,
private router: Router
) { }

ngOnInit() {
this.route.paramMap.subscribe(params => {
const id = params.get('id');
this.loadPost(id);
});
}

loadPost(id: string) {
this.loading = true;
this.blogService.getPostById(id).subscribe(
post => {
this.post = post;
this.loading = false;
},
error => {
this.error = true;
this.loading = false;
// Redirect to 404 after a delay
setTimeout(() => this.router.navigate(['/not-found']), 3000);
}
);
}
}

Summary

Angular Routing is a powerful system that allows you to create complex navigation structures in your Single Page Applications. In this guide, we've covered:

  • Setting up basic routing in an Angular application
  • Creating navigation links with routerLink
  • Working with route parameters for dynamic content
  • Programmatic navigation using the Router service
  • Using query parameters and fragments
  • Building a realistic blog application with routing

By mastering these routing fundamentals, you're well on your way to creating sophisticated Angular applications with intuitive navigation experiences that match what users expect from modern web applications.

Additional Resources and Exercises

Resources

Exercises

  1. Basic Navigation: Create a simple application with three routes: Home, Products, and Contact. Add a navigation menu that highlights the active route.

  2. Dynamic Routes: Create a product listing page that links to individual product detail pages using route parameters.

  3. Query Parameters: Extend the product listing page to include filtering options (e.g., by category, price range) using query parameters.

  4. Not Found Page: Create a custom 404 page and configure the wildcard route to direct users there.

  5. Advanced Challenge: Implement a multi-step form wizard where each step is a different route, and ensure users can't skip steps by directly accessing URLs.

By practicing these exercises, you'll gain a solid understanding of Angular routing principles that you can apply to any application.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)