The Angular router is a very powerful tool that allows us to do all the routing things needed. The router allows us to:

One of the most common tasks when using the router is to create routes with parameters. For instance, here on Scotch, we have user profile links: https://scotch.io/@chris. The chris part of that is a dynamic route parameter.

The Two Ways to Grab Route Parameters

The router provides a couple different ways to grab route parameters. We'll explore both of these and talk about the benefits and cons of each:

  • The Snapshot Way: The router provides us with a snapshot of the current route
  • The Observable/Stream Way: Since Angular employs Observables heavily, the router also returns an Observable that we can listen to.

We'll talk more on both of these options soon.

Creating Routes with Parameters

Let's get the simple stuff out of the way. We'll create a route that has a route parameter.

// app-routing.module.ts

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'users/:username',
    component: UserComponent
  }
];

Note: This is a piece of code out of the AppRoutingModule that the Angular CLI creates by default when you run ng new my-app --routing.

The way that we create a route parameter is with the colon . Here we have a route with :username as the route parameter.

Linking to Routes with Parameters

We'll need to create routes to both of these sections. Here's the various ways we can link to the home page. The Angular router provides us with the RouterLink directive. All of the following achieve the same effect.

<!-- basic routerLink -->
<a routerLink="/">Home</a>

<!-- using the property binding with a string -->
<a [routerLink]="'/'">Home</a>

<!-- using the directive with a full array passed in -->
<a [routerLink]="['/']">Home</a>

Since this route doesn't have any parameters, you can go ahead and use the first option. You can use the second option if you like having the bracket property binding so it's easy to read as an Angular directive. The third option will be useful when we have route parameters.

Linking to the Profile Page with Route Parameters

Here's the ways we can link to the user profiles. In this scenario, we have a variable called username in the corresponding component class.

<a [routerLink]="['/users', username]">{{ username }} Profile</a>

Now that we have our links, we can go look at how we could grab these route parameters in a UserComponent.

Grabbing Route Parameters (The Snapshot Way)

Let's see how we can use the snapshot way to grab route parameters. The Angular Router provides an ActivatedRoute that we can inject into our classes. This will be the main tool we'll use to grab route parameters.

Let's see the basic setup for the UserComponent.

// user.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-user',
  template: `<h1>This is {{ username }}'s profile!</h1>`
})
export class UserComponent implements OnInit {
  username: string;

  // inject the activatated route
  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    // this is where we'll grab data
  }

}

We'll inject the ActivatedRoute into this component via the constructor. Next we'll use the ActivatedRoute to grab the username route parameter in ngOnInit()

ngOnInit() {
  // this is where we'll grab data
  // grab using the snapshot method
  this.username = this.route.snapshot.params.username;
}

This will be enough to grab the username! Let's look at the next way we can grab route parameters and why we would want to use the second method instead of the snapshot method.

Angular Route Performance

Angular works hard to keep application as fast as possible. One of the ways Angular does this is by reusing as often as possible. Angular doesn't have to destroy and recreate multiple times, it will just switch out the data.

Angular reuses components to improve performance.

A scenario where the snapshot method wouldn't work is when we are on one profile and click a link to second profile. The snapshot method only runs one time when the component is initiated. The component wouldn't update if we travelled from (/users/chris) to another profile (/users/nick).

If you are sure that you won't be using the same component over and over, you can use the snapshot method. Otherwise, we'll look to the observable way to

Grabbing Route Parameters (The Observable Way)

Observables by their nature are a stream of events. This means that when we go from one profile (/users/chris) to another profile (/users/nick), the Observable will pass along the new data as it changes.

Angular v4+ router provides us with ParamMap which is an Observable we can use. Here's the syntax to use it instead of the snapshot method:

ngOnInit() {
  // subscribe to the parameters observable
  this.route.paramMap.subscribe(params => {
    console.log(params.get('username'));
    this.username = params.get('username');
  });
}

Now whenever we click to a new profile, you'll see the console.log() updating to show the username from the route.

Note: The Angular router will handle unsubscribing from ParamMap on its own.

Angular v2

The paramMap is one of the newer additions. If you're working with Angular v2 instead of v4+, you can grab route parameters with params instead of paramMap.

ngOnInit() {
  // subscribe to the parameters observable
  this.route.params.subscribe(params => {
    console.log(params.username);
    this.username = params.username;
  });
}

With just a few more lines of code, this component will listen for route changes now and always update the username based on the route.

Conclusion

The Angular router makes it easy to work with route parameters. Remember to weigh your options when deciding between the snapshot vs the Observable way. Usually it's best to lean towards the Observable way just to avoid any issues you may run into in the future if you run into a scenario where you reuse a component.