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:
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:
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:
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 theHomeComponent
/about
shows theAboutComponent
/contact
shows theContactComponent
- 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:
<!-- 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.
Navigation with RouterLink
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.
<a routerLink="/about">About</a>
Active Route Styling
You can style the active route links using the routerLinkActive
directive:
<a routerLink="/about" routerLinkActive="active-link">About</a>
Then in your CSS, you can define the styles for the active link:
.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
const routes: Routes = [
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent },
// other routes...
];
Linking to a Route with Parameters
<a [routerLink]="['/products', product.id]">View {{ product.name }}</a>
Accessing Route Parameters in a Component
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:
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.
Adding Query Parameters with RouterLink
<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
// 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
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.
<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
// 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
<!-- 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
<!-- 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
// 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
- Angular Router Official Documentation
- Angular University - Angular Router In Depth
- Angular's Router Animations
Exercises
-
Basic Navigation: Create a simple application with three routes: Home, Products, and Contact. Add a navigation menu that highlights the active route.
-
Dynamic Routes: Create a product listing page that links to individual product detail pages using route parameters.
-
Query Parameters: Extend the product listing page to include filtering options (e.g., by category, price range) using query parameters.
-
Not Found Page: Create a custom 404 page and configure the wildcard route to direct users there.
-
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! :)