08/07/2016
Updating Your Angular 2 App to Use the New Router: A Practical Guide
JUL 7TH, 2016 | COMMENTS
This week I’ve been updating my Getting Started with Angular 2 Step by Step series from the beta in which they were written to the latest version of Angular which is now RC4.
I had heard about the router debacle but I wasn’t aware of the massive changes required to move from the router in the beta until I updated the articles. I thought it would be helpful to write a quick, super practical guide while it’s fresh in my head. So if you’ve been postponing the router update until now, I hope this guide will help you.
Angular 2 Getting Started
Updating the Angular 2 Router Step by Step
These are the steps that you’ll need to follow to update the router:
Create a separate router configuration file
Remove routes name property
Remove the first / from the path property
Use route redirects instead of useAsDefault
Export your application route configuration
Apply that configuration when bootstrapping your Angular 2 app
Update your [routeLink] directives
Use the new ActivatedRoute service instead of RouteParams
Add a base element inside the your HTML markup
1. Create a Separate Router Configuration File
In Angular 2 beta we used the decorator to both define the routes of our application and apply them to our route component directly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Component } from 'angular2/core';
import { PeopleListComponent } from './people-list.component';
import { RouteConfig } from 'angular2/router';
({...})
([
{
path: '/persons',
name: 'Persons',
component: PeopleListComponent,
useAsDefault: true
},
{
path: '/persons/:id',
name: 'Person Details'
component: PersonDetailsComponent
},
])
export class AppComponent {
title:string = 'Star Wars Peoplez!';
}
With the new component router you specify the configuration in a separate module. For instance, app.routes.ts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { provideRouter, RouterConfig } from '/router';
import { PeopleListComponent } from './people-list.component';
// Route config let's you map routes to components
const routes: RouterConfig = [
// map '/persons' to the people list component
{
path: 'persons',
component: PeopleListComponent,
},
// map '/persons/:id' to person details component
{
path: 'persons/:id',
component: PersonDetailsComponent
},
// map '/' to '/persons' as our default route
{
path: '',
redirectTo: '/persons',
pathMatch: 'full'
},
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
There’s several things to highlight here. First, the router is placed in a different module. We go from:
1
import { RouteConfig } from 'angular2/router';
to:
1
import { RouteConfig } from '/router';
Then the RouteConfig is no longer a decorator but an array of routes. The routes themselves no longer have a name nor useAsDefault properties and the path property leading / is removed.
Default routes are defined as redirects:
1
2
3
4
5
6
7
8
9
10
11
12
// Route config let's you map routes to components
const routes: RouterConfig = [
// this means that the default route
// is the /persons route
{
path: '',
redirectTo: '/persons',
pathMatch: 'full'
},
{...},
{...}
];
Having defined the routes, we need to make the rest of the application aware of them. We use the provideRouter function for that:
1
2
3
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
This defines an APP_ROUTER_PROVIDERS export that not only includes our application routes but also router services suchs as the Router or ActivatedRoute (the new RouteParams).
2. Apply that configuration when bootstrapping your Angular 2 app
In the previous section we saw how we use the app.routes.ts module to define the routing configuration of our app and expose it as an export. The next step is to connect this configuration to our app.
In this new version of Angular 2 we do that while bootstrapping our application often located in a main.ts module:
1
2
3
4
5
import { bootstrap } from '/platform-browser-dynamic';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { AppComponent } from './app.component';
bootstrap(AppComponent, [APP_ROUTER_PROVIDERS]);
This will establish our application routes and provide the different routing services to the various components.
3. Update your [routeLink] values to arrays of values
The [routeLink] directive helps you compose routes based on your routing configuration. In the beta, having defined a parameterized route like this:
1
2
3
4
5
{
path: 'persons/:id',
name: 'Person Details'
component: PersonDetailsComponent
},
The corresponding link would be created as follows:
1
But in the latest router we do the following:
1
That is:
we no longer use the name to create a route link, and instead we use the path
we no longer use an object as a container for the parameterized values but continue adding values to the link array.
4. Use the new ActivatedRoute service instead of RouteParams
In Angular 2 beta we used the RouteParams service to retrieve the parameters from a route when initializing a component. In the latest version on Angular 2 this role falls on ActivatedRoute.
So instead of importing this service:
1
import { RouteParams } from 'angular2/router';
You’ll import this one:
1
import { ActivatedRoute } from '/router';
Where the RouteParams service exposed a get method that you could use to retrieve the parameters of a route:
1
2
3
4
ngOnInit(){
let id = Number.parseInt(this._routeParams.get('id'));
this.person = this._peopleService.get(id);
}
The ActivatedRoute service offers a params observable that lets you access the parameters of a route in an asynchronous fashion:
1
2
3
4
5
6
ngOnInit(){
this.route.params.subscribe(params => {
let id = Number.parseInt(params['id']);
this.person = this.peopleService.get(id);
});
}
A complete example of using ActivatedRoute could look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { Component, OnInit, OnDestroy } from '/core';
import { ActivatedRoute } from '/router';
import { Person } from './person';
import { PeopleService } from './people.service';
({
selector: 'person-details',
template: `
You selected:
Description
weights and is tall.
`
})
export class PersonDetailsComponent implements OnInit, OnDestroy {
person: Person;
sub: any;
constructor(private peopleService: PeopleService,
private route: ActivatedRoute){
}
ngOnInit(){
this.sub = this.route.params.subscribe(params => {
let id = Number.parseInt(params['id']);
this.person = this.peopleService.get(id);
});
}
ngOnDestroy(){
this.sub.unsubscribe();
}
}
5. Add a base element inside the your HTML markup
The new router expects you to have a base element in the head section of your HTML markup (in the index.html, _Layout.cshtml or whichever file holds your application markup):
1
2
3
4
5
6
7
8
My app
This element enables the HTML 5 history.pushState api that let’s Angular 2 provide “HTML5 style” URLs (as opposed to using # prefixed ones).
And that’s it! Now everything should just work.
Would You Like to Learn More About the New Router?
Then check any of these great articles that contain a ton of information about it:
Angular Router by Victor Savkin updated with the latest Angular 2 router
Angular Router: Empty Paths, Componentless Routs and Redirects also by Viktor Savkin with extra information about corner cases for the Angular 2 router
Angular 2 Router straight from the Angular 2 docs with a great coding sample
Routing in Angular 2 Revisited from the thoughtram blog
Your 2 to Use the : A –