Thanks to the ability of share link, websites has been very popular from the day it was born. That’s why the abilities to create link and handle application state base on browser’s url are very important for any web framework.
In Angular 1, we usually work with ngRoute and ui-router. These library works well, but because of the nature of Angular 1, they all have same problem: they separate controller and template, make it very difficult to test. Angular 2 comes with its own router library and it works directly with component. It’s a great improvement compare with Angular 1.
In this articles, we will explorer some basic usages of Angular 2 router, includes:
There is already a very good article from Angular.io website, so instead write a long article, this article is difference because I write it very simple and you can jump into any section and pickup the information immediately.
Before you read the rest of this article, you might want to play with this example, I make it to demonstrate Angular 2 router:
Click on the image to play with it.
( You might think that I am a fan of League of Legend. Well, I am not )
Load router libraries
Here is an example of our index.html
<html> <head> <title>Angular 2 Music</title> <base href="/"> <script src="node_modules/angular2/bundles/angular2.dev.js"></script> <script src="node_modules/angular2/bundles/http.dev.js"></script> <script src="node_modules/angular2/bundles/router.dev.js"></script> <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true } }); System.import('src/App.ts'); </script> </head> <body> <app>Loading</app> </body> </html>
Let’s me explain the steps we need to load the router:
- Add router bundles to index.html. Router library is not included in main package of Angular 2 by default, you have to add it by your self.
- Add <base href> to your document’s head. Honestly, I never knew this element until I used this router. So Angular 2 router uses Html 5 history.pushState to navigate, in order to work properly, we must add <base href> to our document.
Configure routes
Now our app is already ready to use the router. Let’s configure the routes for our app.
import {Component} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'; import {RouteConfig, ROUTER_PROVIDERS, ROUTER_DIRECTIVES} from 'angular2/router'; import {ChampionListCmp} from './ChampionList/ChampionList.cmp.ts'; import {ChampionDetailViewCmp} from './ChampionDetailView/ChampionDetailView.cmp.ts'; @RouteConfig([ {path: '/list', name: 'ChampionList', component: ChampionListCmp, useAsDefault: true}, {path: '/details/:id', name: 'ChampionDetailView', component: ChampionDetailViewCmp } ]) @Component({ selector: 'app', template:` <router-outlet></router-outlet> `, directives: [ROUTER_DIRECTIVES], providers: [ROUTER_PROVIDERS] }) export class AppCmp { } bootstrap(AppCmp);
Sometimes, we might wonder about those ***_PROVIDERS. We have HTTP_PROVIDERS and now ROUTER_PROVIDERS and a lot of them. It’s a good questions, they are the constants from Angular 2 which hold the list of dependency our application needs to load to make those libraries work properly.
Just like our service need to declare and bootstrap by our app, those libraries are not exception.
About ROUTER_DIRECTIVES, it’s a constant too. That constant hold the list of common directives like: RouterOutlet and RouterLink. So instead of import one by one, we import all common directives from router library at once.
Now we have the most important decorator: @RouteConfig
With this decorator, we can configure the routes directly with our component. Each element in route definitions have these properties:
- Path: the path of this route. If this route has another sub route, you need to add three dot ( … ) after the path value.
- Name: name of this route. We don’t use it now, but we will need it when create router link.
- Component: the component will be displayed in RouterOutlet when browser path matches route’s path.
- useAsDefault (optional): if value of this property is true and no route is used. Our app will redirect to this route.
In the template, we need to append <router-outlet></router-outlet>, it just like ui-view from ui-router of Angular 1. When using RouterOutlet, we don’t need to declares our components in the directives property of host component.
Create link
Angular 2 router comes with RouterLink directive helps us create link. Here is a some usages of routerLink:
Link with no parameters:
<a [routerLink]="['ChampionDetailView']">Link</a>
The first parameter is the route’s name from RouteConfig
Link with parameters:
<a [routerLink]="['ChampionDetailView', {id: champion.Id}]">
Now we have second parameter, in order to make it works, you need to remember to configure routes properly:
@RouteConfig([ {path: '/details/:id', name: 'ChampionDetailView', component: ChampionDetailViewCmp } ])
Extract url parameters
Let’s say our app visit a url which has some parameters, for example: http://localhost/details/1. How to extract that parameter and use it in our app ?
We got RouteParams comes to help us in this case, it’s a service so we can inject to our component. I usually use it with ngOnInit. Here is an example of RouteParams:
import {Component, OnInit} from 'angular2/core'; import {RouteParams} from 'angular2/router'; import {LOLService} from '../LOLService.service.ts'; @Component({ selector: 'champion-detail-view', template: ` <h3>{{champion.Name}}</h3> <p>{{champion.Description}}</p> `, styles: [` .champion-image { margin: 0 auto; } `] }) export class ChampionDetailViewCmp implements OnInit { private champion: any; constructor(private routeParams: RouteParams, private lolService: LOLService) { this.champion = null; } ngOnInit() { var Id = parseInt(this.routeParams.params['id']); this.champion = this.lolService.getChampionById(Id); } }
Conclusion
The reason that I love new Angular 2 router is we can configure routes directly with component. New router is also very easier to use. The configuration of ui-route in Angular 1 works well, but it’s the pain in ass to write test and easy lead to errors since a controller can be used by many different routes.
Another nice thing about Angular 2 route is we can combine it with angular-universal to make a sever-side rendering works. It’s one of the biggest selling point of Angular 2!
Stay tune.