Angular 2

TRAINING
Angular 2
OVERVIEW

ngular 2: ABOUT

-
Mobile first
-
Modular
-
COMplete rewrite
-
Modern browsers
-
WRITTEN in TYPESCRIPT
ngular 2: LANGUAGES

ES5
ES6
TS
DART
ngular 2: TYPESCRIpt 101

-
CLass (declaration)
class Car {
}
public brand: string;
public number: number;
public isCarNew: boolean;
constructor(brand: string, number: number, isCarNew: boolean){
this.brand = brand;
this.number = number;
this.isCarNew = isCarNew;
}
ngular 2: TYPESCRIpt 101

-
CLass (methods)
class Car {
}
constructor(public brand: string,
public number: number,
public isCarNew: boolean) { }
getCarNumber(): number {
return this.number;
}
setCarNumber(newNumber: number): void {
this.number = newNumber;
}
ngular 2: ARCHITECTURE

App component (cmp)
cmp 1
cmp 2
cmp 3
cmp 4
A tree of components
ngular 2: ARCHITECTURE

component
template
DIREctive
property binding
Event binding
injector
Service
app module
my module
Angular 2
components

ngular 2: COMponents

@Component({
})
export class MyCardComponent {
}
import { Component } from '@angular/core';
selector: 'my-card',
templateUrl: 'my-card.component.html',
styleUrls: ['my-card.component.css']
Component Metadata Properties:
animations - list of animations of this component
changeDetection - change detection strategy used by this component
encapsulation - style encapsulation strategy used by this component
entryComponents - list of components that are dynamically inserted into the view
of this component
exportAs - name under which the component instance is exported in a template
host - map of class property to host element bindings for events,
properties and attributes
inputs - list of class property names to data-bind as component inputs
interpolation - custom interpolation markers used in this component's template
moduleId - ES/CommonJS module id of the file in which this component is defined
outputs - list of class property names that expose output events that
others can subscribe to
providers - list of providers available to this component and its children
queries - configure queries that can be injected into the component
selector - css selector that identifies this component in a template
styleUrls - list of urls to stylesheets to be applied to this component's view
styles - inline-defined styles to be applied to this component's view
template - inline-defined template for the view
templateUrl - url to an external file containing a template for the view
viewProviders - list of providers available to this component and its view children
ngular 2: Templates

-
interpolation
<p>Hello, my name is {{ user.firstName }}</p>
<p>Hello, my name is {{ getUserFistName() }}</p>
ngular 2: Templates

-
bindings
// one-way binging (data source => view target)
<user-profile [user]="user"></user-profile>
[target]="expression"
// one-way binging (target => data source)
(target)="statement"
<my-card (click)="select()"></my-card>
// two-way binging (data source <=> view target)
[(target)]="expression"
<input type="text" [(ngModel)]="user.firstName">
ngular 2: BUILD-in dirs

-
ngClass
-
ngStyle
-
ngIf
-
ngFor
-
ngSwitch
ngular 2: ngfor

-
ngFor
// notice asterisk (*) symbol
<li *ngFor="let user of users">{{user.fullName}}</li>
<user-profile *ngFor="let user of users" [user]="user">
<user-fullname>{{ user.fullName }}</user-fullname> </user-profile>
ngular 2: ngclass

-
ngClass
// toggle one class
<div [class.cool]="isCool">This div is cool</div>
setClasses() {
let classes = {
bordered: this.isBordered,
blue: this.isBlue
};
return classes;
}
// toggle multiple classes
<div [ngClass]="setClasses()">
This div is bordered and blue
</div>
ngular 2: data flow

-
parent => child
application
users
user
user
cards
[users]="appUsers"
[user]="users"
ngular 2: INPUTS

-
@input
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'user',
templateUrl: 'user.component.html',
styleUrls: ['user.component.css']
})
export class UserComponent {
}
, Input
// user.component.html
<div class="fullName">{{ user.fullName }}</div>
@Input() user;
ngular 2: data flow

-
CHILD => parent
application
users
user
user
cards
(select)="onSelect()"
(select)="onSelect()"
ngular 2: outputs

-
@output
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'user',
templateUrl: 'user.component.html',
styleUrls: ['user.component.css']
})
export class UserComponent {
}
, Output, EventEmitter
// users.component.html
@Output() select = new EventEmitter();
onSelect() { this.select.emit(...); }
<user (select)="onSelected()"></user>
ngular 2: Nested cmps

-
child => parent components
// users.component.html
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'users',
templateUrl: 'users.component.html',
styleUrls: ['users.component.css'],
})
export class UsersComponent {
}
import { UserComponent } from './../user.component';
directives: [UserComponent]
<div>
<user [user]="user"></user>
</div>
deprecated!
ngular 2: CMP lifecycle

-
component lifecycle hooks
- ngOnInit
- ngOnChanges
- ngDoCheck
- ngOnDestroy
ngular 2: oninit

-
ngOnInit
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-card',
templateUrl: 'my-card.component.html',
styleUrls: ['my-card.component.css']
})
export class MyCardComponent {
}
, OnInit
implements OnInit
ngOnInit() {
...
}
Angular 2
ngmodules

ngular 2: ngmodules

app module
http module
forms module
Users module
Auth module
ngular 2: ngmodules

-
@ngModule
import { NgModule } from '@angular/core';
@NgModule({
imports: [ ... ], // other modules
declarations: [ ... ], // components, directives, pipes
exports: [ ... ], // components, directives, pipes
providers: [ ... ] // services
})
export class MyModule { }
ngular 2: App module

-
AppModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
ngular 2: Custom module

-
UsersModule
@NgModule({
imports: [ HttpModule, FormsModule, AuthModule ],
declarations: [ UserComponent, StatusPipe ],
exports: [ UserComponent ],
providers: [ UserService ]
})
export class UsersModule { }
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { AuthModule } from './../auth/auth.module';
import { UserComponent } from './user.component';
import { UserService } from './user.service';
import { StatusPipe } from './status.pipe';
Angular 2
services & Dependency injection

ngular 2: Services & Di

-
UsersService
import { IUser } from './../users/user';
export class UsersService { getUsers() { ... } updateUser(user: IUser) { ... } }
import { Injectable } from '@angular/core';
@Injectable()
import { AuthService } from './../../auth/auth.service';
constructor(private auth: AuthService) { }
ngular 2: Services & Di

// visible for all components inside this module
import { UserService } from './../users/user.service';
@NgModule({
imports: [ ... ],
declarations: [ ... ],
exports: [ ... ],
providers: [ UserService ]
})
export class UsersModule { }
// visible only for this component and its children
import { UserService } from './../users/user.service';
@Component({
selector: 'my-card',
providers: [ UserService ]
})
export class MyCardComponent { }
ngular 2: Services & Di

-
http service
import { HttpModule } from '@angular/http';
@NgModule({
imports: [ HttpModule ],
declarations: [ ... ],
providers: [ ... ],
bootstrap: [ ... ]
})
export class AppModule { }
ngular 2: Services & Di

-
UsersService
class UsersService {
private usersUrl: string = 'api/v1/users';
constructor(private http: Http) { }
getUsers() {
return this.http.get(this.usersUrl)
.toPromise()
.then(response => response.json().data)
.catch(this.handleError);
}
private handleError(error: any) { ... }
}
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
ngular 2: Services & Di

-
UsersService
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
class UsersService {
private usersUrl: string = 'api/v1/users';
constructor(private http: Http) {}
createUsers(user: User) {
return this.http.post(
this.usersUrl,
JSON.stringify(user),
{headers: headers})
.toPromise()
.then(response => response.json().data)
.catch(this.handleError);
}
}
, Headers
let headers = new Headers({'Content-Type': 'application/json'});
Angular 2
DEMO TIME :)

Angular 2
ROUting

ngular 2: cmp router

<head>
<base href="/">
...
</head>
// set <base href>
// app/app.routing.ts
import { Routes, RouterModule } from '@angular/router';
const appRoutes: Routes = [
{ path: 'users', component: UsersComponent }
];
import { UsersComponent } from './users.component';
export const routing = RouterModule.forRoot(appRoutes);
ngular 2: cmp router

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { UsersComponent } from './users.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, UsersComponent ],
providers: [ ... ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
import { routing } from './app.routing';
, routing
ngular 2: cmp router

// navigation
@Component({
...
template: `
<div class="content">
</div>
`
})
export class AppComponent {}
<router-outlet></router-outlet>
<nav>
<a routerLink="/users" >Users</a>
</nav>
routerLinkActive="active"
ngular 2: cmp router

// users.routing.ts
-
Users feature module
import { Routes, RouterModule } from '@angular/router';
import { UsersComponent } from './users.component';
import { UserComponent } from './user.component';
const usersRoutes: Routes = [
{
path: 'users',
component: UsersComponent,
children: [
{ path: ':id', component: UserComponent },
]
}
];
export const usersRouting = RouterModule.forChild(usersRoutes);
ngular 2: cmp router

// users.module.ts
-
Users feature module
import { usersRouting } from './users.routing';
@NgModule({
imports: [ ..., ],
declarations: [ ... ],
providers: [ ... ]
})
export class UsersModule { }
usersRouting
ngular 2: cmp router

-
Users component
import { Component } from '@angular/core';
@Component({
selector: 'users',
...
})
export class UsersComponent {
}
import { Router } from '@angular/router';
constructor(private router: Router ) { }
viewUser(user: User) {
this.router.navigate(['/user', user.id]);
}
import { User } from './../user';
ngular 2: cmp router

-
router guards
- CanActive
- CanDeactivate
- Resolve
ngular 2: cmp router

-
CanDeactive guard
import { Component } from '@angular/core';
import { CanDeactivate } from '@angular/router';
@Component({
selector: 'user',
...
})
export class UserComponent {
}
implements CanDeactivate
canDeactivate() {
...
}
ngular 2: cmp router

-
Lazy loading modules
const ROUTES = [
{
path: 'users',
},
{
path: 'cars',
}
];
@NgModule({
...
bootstrap: [AppComponent],
imports: [RouterModule.forRoot(ROUTES)]
})
class AppModule {}
loadChildren: 'users.bundle.js',
loadChildren: 'cars.bundle.js',
Angular 2
forms

ngular 2: Forms module

-
Importing forms module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
import { FormsModule } from '@angular/forms';
, FormsModule
ngular 2: Forms

-
profile component
// profile.component.html
<form>
<div class="form-group">
<label for="fName">First name</label>
<input type="text" id="fName" required >
</div>
<div class="form-group">
<label for="lName">Last name</label>
<input type="text" id="lName" >
</div>
<button type="submit" class="btn btn-default">Save</button>
</form>
@Component({
selector: 'profile',
templateUrl: 'profile.component.html',
...
})
export class ProfileComponent { }
// profile.component.ts
[(ngModel)]="user.firstName"
[(ngModel)]="user.lastName"
ngular 2: Forms

-
control state classes
State | Class if true | Class if false |
---|---|---|
Control has been visited |
ng-touched | ng-untouched |
Control's value has changed |
ng-dirty | ng-pristine |
Control's value is valid |
ng-valid | ng-invalid |
ngular 2: Forms

-
validation messages
<form>
...
<div class="form-group">
<label for="fName">First name</label>
<input type="text" id="fName" required
[(ngModel)]="user.firstName" >
</div>
</form>
// #fName is a reference to a DOM element within template
#fName="ngModel"
<div [hidden]="fName.valid || fName.pristine" class="alert alert-danger">
First name is required
</div>
ngular 2: Forms

-
form SUBMIT
<form >
<div class="form-group">
<label for="fName">First name</label>
<input type="text" id="fName" required
[(ngModel)]="user.firstName">
</div>
...
<button type="submit" class="btn btn-default"
>Save</button>
</form>
(ngSubmit)="onSubmit()"
#profileForm="ngForm"
[disabled]="!profileForm.form.valid"
// ngForm directive is added to each form by Angular
Angular 2
Pipes

ngular 2: pipes

-
date pipe
// 'Aug 23, 2016' <p>Last login: {{ user.lastLogin | date }}</p>
// 'Aug 23, 2016, 9:45:15 PM'
<p>Last login: {{ user.lastLogin | date:'medium' }}</p>
// '9:45:15 PM'
<p>Last login: {{ user.lastLogin | date:'shortTime' }}</p>
// '45:15'
<p>Last login: {{ user.lastLogin | date:'mmss' }}</p>
ngular 2: Built-in pipes

-
built-in pipes
- DatePipe
- UpperCasePipe
- LowerCasePipe
- CurrencyPipe
- PercentPipe
ngular 2: custom pipe

import { Pipe, PipeTransform } from '@angular/core';
- toSeconds pipe
@Pipe({name: 'ToSeconds' })
export class ToSecondsPipe implements PipeTransform {
transform(value: number): number {
// translate milliseconds to seconds
return Math.round(value / 1000);
}
}
Angular 2
Angular 1.x and upgrade

ngular 2: Angular 1.5.x

-
module.component
angular
.module('myApp')
.component('userProfile', {
});
templateUrl: 'userProfile.component.html',
controller: UserProfileController,
class UserProfileController {
...
}
bindings: {
user: '<', // one-way binding (input)
onSelect: '&' // event callback (output)
}
ngular 2: Cmp lifecycle

-
component lifecycle hooks
- $onInit()
- $onChanges
- $doCheck()
- $onDestroy()
ngular 2: ui-router 1.0

-
route state
$stateProvider
.state('root', {
url: '/users',
component: 'Users',
});
angular
.module('myApp')
.component('users', {
bindings: {
users: '<'
}
});
// resolved bindings pass automatically
resolve: {
users: function(UsersService) {
return UsersService.getUsers();
}
}
ngular 2: upgrade

a1
a1
a1
a2
a2
a2
ngular 2: upgrade adApter

-
angular 2 cmp => angular 1
import { UpgradeAdapter } from '@angular/upgrade';
import { UserProfileComponent } from './user-profile.component';
angular
.module('myApp')
.directive('userProfile',
);
UpgradeAdapter.downgradeNg2Component(UserProfileComponent));
ngular 2: upgrade adapter

-
angular 1 Cmp => angular 2
import { UpgradeAdapter } from '@angular/upgrade';
import { Component } from '@angular/core';
const UserAvatar = UpgradeAdapter.upgradeNg1Component('userAvatar');
@Component({
selector: 'user-profile',
template: `
<div>
<user-avatar></user-avatar>
</div>
`,
})
export class UserProfileComponent { }
directives: [UserAvatar]
Angular 2
Conclusion

ngular 2: Final notes

- angular.io
- Angular Official Style Guide
- Angular Cheat Sheet
- Angular CLI
- Codelyzer
- Material2
- Augury
Thank you!
questions time ;)

Angular 2
By rahul bussa
Angular 2
A full version of presenation
- 1,061