Angular 2 Component Router
by Gerard Sans (@gerardsans)
Google Developer Expert
Master of Ceremonies
International Speaker
Angular 2 Trainer
Community Leader
800
500
Component Router
Main Contributor
Main Features
- Based on components
- Flexible routing
- Nested views, auxiliary routes
- Router Lifecycle Hooks
- Lazy loading
Some days before the conference...
/home
/users
/about
/users/34
Setup Router
Dependencies
- Include bundle: router.js
- Choose Location Strategy
- Include providers
- ROUTER_PROVIDERS
- Include directives
- ROUTER_DIRECTIVES
Location Strategies
- HashLocationStrategy
- Eg: #/home, #/users/34
- PathLocationStrategy (default)
- Requires
APP_BASE_HREF
- Eg: /home, /users/34
- Requires
Defining Routes
import {RouteConfig} from 'angular2/router';
import {Home} from './home';
import {Users} from './users';
import {AboutLazyLoader} from './aboutLazyLoader';
@RouteConfig([
{ path: '/home', component: Home, name: 'Home', data: {level:0} },
{ path: '/users/...', component: Users, name: 'Users' },
{ path: '/about', loader: AboutLazyLoader , name: 'AboutLazyLoad' },
{ path: '/**', redirectTo: ['Users'] }
])
export class App { }
Outlets
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
selector: 'my-app',
template: `
<nav>...</nav>
<div>
<router-outlet></router-outlet>
</div>`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig(...)
export class App { }
Flexible Routing
Child Routes
- Parent uses special mark
-
/users/...
-
- Child defines its own routes
- Always define a default route
-
useAsDefault: true
-
Child Routes
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {UsersList} from './usersList';
import {UserDetails} from './userDetails';
@Component({
selector: 'users',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{ path: '/', component: UsersList, name: 'UsersList', useAsDefault: true },
{ path: ':id', component: UserDetails, name: 'UserDetails' },
])
export class Users { }
/
UsersList
#/users, #/users/
:id
UserDetails
#/users/34
Navigation
- Using regular links with hash
-
#/home
-
- Using routerLink directive uses link DSL
-
['Home']
-
['/Users/UserDetails', {id: 34}]
-
- Programatically
-
router.navigate(['Home']);
-
router.navigateByUrl('/home');
-
routerLink
<!-- Top Routes -->
<a [routerLink]="['Home']">Home</a>
<a [routerLink]="['Users']">Users</a>
<a [routerLink]="['AboutLazyLoad']">About</a>
<!-- Nested Routes -->
<a [routerLink]="['/Users/UsersList']">Users</a>
<a [routerLink]="['/Users/UserDetails', {id: 34}]">Spiderman</a>
<a [routerLink]="['/Users/UserDetails', {id: 34, flag: true}]">Spiderman</a>
<!-- Relative Routes -->
<a [routerLink]="['./UsersList']">Users</a>
<a [routerLink]="['./UserDetails', {id: 34}]">Spiderman</a>
<a [routerLink]="['./UserDetails', {id: 34, flag: true}]">Spiderman</a>
Auxiliary routes
@Component({
selector: 'my-app',
template: `
<router-outlet></router-outlet>
<router-outlet name="modal"></router-outlet>`,
})
@RouteConfig([
{path: '/hello', component: HelloCmp, name: 'Hello'}),
{aux: '/modal', component: ModalCmp, name: 'Modal'})
])
export class App { }
<a [routerLink]="['/Hello', ['Modal']]">both</a>
router.navigateByUrl('/hello(modal)'))
<a [routerLink]="['/', ['Modal']]">only modal</a>
router.navigateByUrl('/(modal)'))
Accessing Parameters
/*
{ path: ':id', component: UserDetails, name: 'UserDetails' }
*/
import {RouteParams} from 'angular2/router';
@Component({
selector: 'user-details'
})
export class UserDetails {
constructor(private params: RouteParams){
let id = params.get('id');
}
}
Accessing Data
/*
{ path: '/home', component: Home, name: 'Home', data: {level:0} }
*/
import {RouteData} from 'angular2/router';
@Component({
selector: 'home'
})
export class Home {
constructor(private data: RouteData){
console.log(data.get("level"));
}
}
Router Lifecycle Hooks
Navigation from users list to user details
- UsersList.routerCanDeactivate()
- UserDetails.@CanActivate()
- UsersList.routerOnDeactivate()
- UserDetails.routerOnActivate()
Save changes
@Component({
selector: 'user-details'
})
export class UserDetails implements CanDeactivate {
routerCanDeactivate() {
return new Promise(resolve =>
resolve(window.confirm('Do you want to continue?'))
);
}
}
Block Access
@Component({
selector: 'user-details'
})
@CanActivate(next => {
let injector = appInjector();
let service = injector.get(LoginService);
return new Promise(resolve => {
resolve(service.authorised);
});
})
export class UserDetails { }
Lazy Loading
Setup
@RouteConfig([
{ path: '/about', loader: AboutLazyLoader , name: 'AboutLazyLoad' }
])
export class App { }
//aboutLazyLoader.ts
export function AboutLazyLoader(){
return System.import('./src/aboutLazyLoad.ts')
.then(module => module.AboutLazyLoad);
}
//aboutLazyLoad.ts
@Component({
selector: 'about',
template: `<h1>About</h1>`
})
export class AboutLazyLoad { }
Demo
Features
- PathLocationStrategy setup
- Nested routes with parameters
- Block leaving route
- Block route access
- SVG loading spinner
- Active menu css style fix
AngularConnect - Sept 27-28th
2x FREE Become a ninja with Angular 2
twit latest ng2 release full name to @gerardsans #rigadevday