Angular 2 - advanced
Routing
One app, multiple screens
What is routing?

Why routing?
- Integrates with the browser history
- User can use "back" and "forward" buttons
- Every screen/state is accessible (represented) by the link
- Easier to navigate and to share resources
Setting the router in Angular 2
//index.html
<head>
<base href="/">Creating AppRoutingModule
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const appRoutes: Routes = [
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Import AppRoutingModule
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Configure main Routes (Lazy Loading)
const appRoutes: Routes = [
{ path: 'dashboard', loadChildren: 'path/to/dashboard.module#DashboardModule' },
{ path: 'transactions', loadChildren: 'path/to/transactions.module#TransactionsModule' },
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }Configure child Routes
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TransactionsComponent } from './transactions/transactions.component';
let moduleRoutes: Routes = [
{
path: '',
component: TransactionsComponent
}
]
@NgModule({
declarations: [
TransactionsComponent
],
imports: [
RouterModule.forChild(moduleRoutes)
],
providers: []
})
export class TransactionsModule { }
Displaying a routing view
<h1>App Header</h1>
<a [routerLink]="['/dahsboard']">Dashboard</a>
<a [routerLink]="['/transactions']">Display list transactions</a>
<router-outlet></router-outlet>Let's code
Application routing
Parametrized routesĀ
{
path: 'user/:id',
component: UserDataComponent
},
// creating a link
<a [routerLink]="['/user', person.id]">
<a [routerLink]="['/user', 666]">
// ...
this.router.navigate(['/user', this.selectedPerson.id]);Working with Router
Extracting parameters
Extract parameters
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
export class UserDataComponent implements OnInit {
constructor(
private route: ActivatedRoute
) {}
ngOnInit(): void {
this.route.params
.subscribe((params: Params) => {
console.log(params['id']);
});
}
}
Let's code
Display user data (id)
Life cycle hooks
List of hooks

Overview
- ngOnChanges - Respond when Angular (re)sets data-bound input properties. Called before ngOnInit and whenever one or more data-bound input properties change.
-
ngOnInit - Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties. Called once, after the first ngOnChanges.
-
ngOnDestroy - Cleanup just before Angular destroys the directive/component. Unsubscribe observables and detach event handlers to avoid memory leaks. Called just before Angular destroys the directive/component.
Server communication
HTTP Requests
Add Http module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
HttpModule,
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }Using http
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import { UserData } from './user-data';
@Injectable()
export class UserssHttpService {
constructor(private http: Http) {}
loadAll(): Observable<UserData[]> {
return this.http
.get(`data/users.json`)
.map((r: Response) => r.json() as UserData[]);
}
}In the component
export class UsersComponent {
records: UserData[];
constructor(private service: UsersHttpService) {
}
ngOnInit() {
this.service.loadAll().subscribe((records: UserData[]) => {
this.records = records;
});
}
}
// template
<div>
<div *ngFor="let user of records">
{{user.name}}
</div>
</div>Using | async pipe
export class UsersComponent {
records: Observable<UserData[]>;
constructor(private service: UsersHttpService) {
}
ngOnInit() {
this.records = this.service.loadAll()
}
}
// template
<div>
<div *ngFor="let user of records | async">
{{user.name}}
</div>
</div>Why Observables/Streams?
ngOnInit(): void {
this.heroes = this.searchTerms
.debounceTime(300) // wait for 300ms pause in events
.distinctUntilChanged() // ignore if next search term is same as previous
.switchMap(term => term // switch to new observable each time
// return the http search observable
? this.heroSearchService.search(term)
// or the observable of empty heroes if no search term
: Observable.of<Hero[]>([]))
.catch(error => {
// TODO: real error handling
console.log(error);
return Observable.of<Hero[]>([]);
});
}Let's code
Loading data from assets/data.json
Angular Change Detection
Every Component has it's own change detector
When some event occurs, CD is triggered
Optimization
- Only one run
- Data flows from top to bottom
- CD code is generated and JIT friendly
- Possible: Primitive components
On Push Change Detection
@Component({
template: `
<h2>{{vData.name}}</h2>
<span>{{vData.email}}</span>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
class VCardCmp {
@Input() vData;
}On Push Change Detection
Angular 2 - advanced
By sosnowsd
Angular 2 - advanced
- 334