This post is part of a series of posts about Angular2. You can find them all in the introduction: https://julienrenaux.fr/2015/11/30/angular2-series-introduction/
BEWARE, SINCE THE RELEASE CANDIDATE THIS ROUTER IS DEPRECATED!
Before we start and to make sure we are in line on the terminology, I will use the name AngularJS to define AngularJS 1.x and Angular2 to define AngularJS 2.x.
All the following code examples are part of a boilerplate I created. It is available on GitHub: https://github.com/shprink/angular2-nobullshit-boilerplate.
If you are used to AngularJS applications you have probably used the ui-router instead of the Angular basic router (ngRoute). The ui-router is more popular because it has more features (such as nested views
) and was adopted by big projects such as Ionic Framework.
The Angular2 router is a complete rewrite of the old ngRoute module. It was created keeping the ui-router use cased in mind, but also Angular2 components based architecture (a concept not yet adopted with AngularJS).
If you want to know more details about the Router history I recommend watching this video (beware the API changed a little bit since this video):
https://www.youtube.com/watch?v=vecg70fPDFw
If you want to know more about components in Angular2 I suggest you to read this previous article of mine: Angular2 series – Component, Directive, Pipe and Service.
Path location strategies
Using AngularJS
With the ui-router
in AngularJS you have the choice between two modes. The default one, aka the Hash
mode (#products/id
) that is not interpreted by servers or the HTML5
mode (/products/id
).
One or the other can be selected using the $locationProvider
$locationProvider.html5Mode(true);
Notice: This HTML5 mode requires your web server to be configured.
Using Angular2
In Angular2 we have the same “modes” but they are called PathLocationStrategy
and HashLocationStrategy
.
PathLocationStrategy
PathLocationStrategy
is the default strategy used by the new router. It is equivalent to the HTML5 mode in AngularJS.
If you want to use this strategy, you must define the APP_BASE_HREF
to a string representing the URL prefix that should be preserved when switching pages.
import {ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';
bootstrap(yourApp, [
ROUTER_PROVIDERS, // includes binding to PathLocationStrategy
provide(APP_BASE_HREF, {useValue: '/my/prefix/here'})
]);
If you have problems understanding the above example, learn how to create an application with Angular2 first by reading: Angular2 series – Component, Directive, Pipe and Service.
If you do not want any prefix to be kept you can set APP_BASE_HREF
to be:
provide(APP_BASE_HREF, {useValue: '/'})
HashLocationStrategy
HashLocationStrategy
is the strategy equivalent to the default strategy in AngularJS ui-router
. This strategy is used to configure the Location service to represent its state with the hash fragment of the browser’s URL.
import {ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy} from 'angular2/router';
bootstrap(yourApp, [
ROUTER_PROVIDERS,
provide(LocationStrategy, {useClass: HashLocationStrategy})
]);
Define Routes
Using AngularJS
In AngularJS and ui-router
here is how to define states
(or Routes) during the configuration phase:
$stateProvider.state('home', {
url: '/',
templateUrl: 'home.html',
controller: 'HomeCtrl'
}).state('about', {
url: '/about',
templateUrl: 'about.html',
controller: 'AboutCtrl'
})
Using Angular2
In Angular2 a state
is created from a Route
class. Using the @RouteConfig
annotation you can create your application route definition.
@RouteConfig
takes as first argument an Array of Route
that have the following properties:
path
equivalent tourl
inui-router
statescomponent
a component type.name
is an optional CamelCase string representing the name of the route.data
is an optional property of any type representing arbitrary route metadata for the given route (we talk about it in the Passing data between routes section)
With that in mind let’s create an equivalent of the routes we created in the AngularJS version:
import {RouteConfig, Route} from 'angular2/router';
import {MyComponentHome, MyComponentAbout} from './myComponents';
@Component({
selector: "app"
})
@RouteConfig([
new Route({ path: '/', component: MyComponentHome, name: 'Home' }),
new Route({ path: '/about', component: MyComponentAbout, name: 'About' })
])
export class App {...}
Template update
We have now defined our Routes, the next step is to define where to display the components when switching pages.
Using AngularJS
In AngularJS and ui-router
we can use the ui-view
directive to insert dynamic content from each state:
<body>
<ui-view>
<i>Some content will load here!</i>
</ui-view>
</body>
Using Angular2
Using Angular2, it is similar, only the name of the directive change!
First we need to import the RouterOutlet
directive and inject it into our App component, then we can use it in our template.
import {RouterOutlet} from 'angular2/router';
@Component({
selector: "app"
})
@View({
directives: [RouterOutlet]
template: `
<router-outlet></router-outlet>
`
})
Now any location change will load a different component inside the RouterOutlet
directive.
Navigate between pages
Using AngularJS
To navigate between pages (or states) in AngularJS and the ui-router
we can use the ui-sref
directive.
<a ui-sref="home">Home page</a>
<a ui-sref="about">About page</a>
Using Angular2
With Angular2 we can use the RouterLink
directive instead.
This directive needs to be injected in your component first:
import {RouterLink} from 'angular2/router';
@Component({
selector: "menu",
directives: [RouterLink],
template: `
<a [routerLink]="['./Home']">Home page</a>
<a [routerLink]="['./About']">About page</a>
`
})
export class Menu {...}
Please note that [routerLink]
uses the Route name
that we defined earlier in the
Passing data between routes
Using AngularJS
In AngularJS we could defined URL parameters in state definitions:
$stateProvider.state('product.item', {
url: '/product/:id',
templateUrl: 'item.html',
controller: 'ItemCtrl'
})
To pass the id from a state to another we have two choices. We can use the ui-sref
directive or the $state
service:
<a ui-sref="product.item({id: 4})">Go to item 4</a>
function($state) {
// Go to item 4
$state.go('product.item', {id: 4});
}
Then getting this data in our controller is easy using the $stateParams
service:
function($stateParams) {
var id = $stateParams.id;
}
BEWARE: The concept of params
(passing data between states but without using URL parameters) in the ui-router
does not exist in Angular2 (see my question on stackoverflow). A similar concept exist though and it is called data
.
Using Angular2
Similar to AngularJS, we can define URL parameters using path
from the Route
class:
@RouteConfig([
new Route({
path: '/product/:id',
component: MyProductItemComponent,
name: 'ProductItem'
})
])
export class App {...}
To pass the id from a Route
to another we also have two choices. We can use the routerLink
directive or the Router
service.
In a template:
<a [routerLink]="['./ProductItem', {id: 4}]">Go to item 4</a>
In a Component:
import {Router} from 'angular2/router';
class {
constructor(private _router: Router) {
this._router.navigate( ['./ProductItem', { id: 4 }] );
}
}
Then getting this data in a Component is easy using the RouteParams
service:
import {RouteParams} from 'angular2/router';
class {
id: number;
constructor(private _params: RouteParams) {
this.id = _params.get('id');
}
}
You can also retrieve data from a Route
using RouteData
service. I think this feature would not be used often (I probably will not use it on my applications) but it is good to know that it exists:
@RouteConfig([
new Route({
path: '/product/:id',
component: MyProductItemComponent,
name: 'ProductItem',
data: {
isAdmin: true
}
})
])
export class App {...}
You can now retrieve the isAdmin
flag or any other Route
metadata in your Components using the RouteData
service:
class {
isAdmin: boolean;
constructor(private _data: RouteData) {
this.isAdmin = _data.get('isAdmin');
}
}
Thanks for reading, you can interact about this post by leaving a comment here, or directly on Twitter and Facebook!