Pour suivre la présentation...
En synchronisé :
En autonomie :
Avant de commencer...
Angular 2
Mikael Couzic
Angular 2 4
Angular
Hello, AngularJS !
<div>
Name: <input ng-model="name">
<h1>Hello {{name}} !</h1>
</div>
Hello, Angular !
@Component({
selector: 'my-app',
template: `
<div>
Name: <input [(ngModel)]="name">
<h1>Hello {{name}} !</h1>
</div>
`,
})
export class App {
}
(ngModel)
Hello, Angular !
@Component({
selector: 'my-app',
template: `
<div>
Name: <input (keyup)="onNameKeyUp($event)">
<h1>Hello {{name}} !</h1>
</div>
`,
})
export class App {
name: string
onNameKeyUp(event: KeyboardEvent) {
this.name = event.target.value
}
}
($event)
Hello, Angular !
@Component({
selector: 'my-app',
template: `
<div>
Name: <input #name (keyup)=0>
<h1>Hello {{name.value}} !</h1>
</div>
`,
})
export class App {
}
(reference variable)
Hello, Angular !
@Component({
selector: 'my-app',
template: `
<div>
Name: <input [formControl]="name">
<h1>Hello {{name.value}} !</h1>
</div>
`,
})
export class App {
name = new FormControl()
}
(reactive form)
Typescript
Extension de JavaScript
ES5
ESNext
TypeScript
-
Compatible avec JavaScript
-
Types statiques
-
Détection d'erreurs dès la compilation
-
Auto-complétion, refactorings...
-
-
Flexibilité du typage structurel
-
Accessible aux développeurs Java et C#
Avantages
Variables et constantes :
let n: number = 1
const s: string = 'Hello'
Annotations de type
Paramètres de fonctions :
function f(i: number) { ... }
Retour de fonction :
function f(): number {
return 42
}
Le compilateur TypeScript induit les types des variables et retours de fonctions non annotés
let n = 1 // let n: number = 1
let s = "Hello World" // let s: string = "Hello World"
n = s; // COMPILATION ERROR
s = n; // COMPILATION ERROR
function f() { // function f(): string {
return "hello"
}
Types implicites
L'équivalent TypeScript du type dynamique
const n: number = 1
const s: string = 's'
function print(a: any) {
console.log(a)
}
print(n)
print(s)
Type "any"
const n = 1
const s = 's'
function printUnion(u: number | string) {
console.log(u)
}
printUnion(n)
printUnion(s)
printUnion(false) // COMPILATION ERROR
Type Union
const n = 1
const s = 's'
type Printable = number | string
function printAlias(p: Printable) {
console.log(p)
}
printAlias(n)
printAlias(s)
Type Alias
interface Person {
name: string
age: number
}
interface Client extends Person {
id: number
address: {
street: string
city: string
}
}
Interfaces
interface Person {
name: string
age: number
}
function sayHello(person: Person): string {
return 'Hello, ' + person.name
}
const bob: Person = {
name: 'Bob',
age: 7
}
sayHello(bob)
sayHello({
name: 'John',
age: 42
})
Typage Structurel
type Drink = 'juice' | 'beer' | 'wine'
function serve(drink: Drink) {}
serve('juice')
const alcoolVolumeByDrink: Record<Drink, number> = {
juice: 0,
beer: 4.5,
wine: 12
}
const wineAlcoolVolume = alcoolVolumeByDrink.wine
TypeScript Tricks
Angular
@Component
@View
@Directive
@Animation
@Inject
@InjectLazy
@Optional
@Host
@Parent
@Pipe
@Property
@NgModule
@RouteConfig
@HostBinding
@HostEvent
@Injectable
@ViewChild
@ViewChildren
@Input
@Output
@Attribute
@CanActivate
import {Component} from '@angular/core';
@Component({
selector: 'greeter',
template: `<h1>Hello !</h1>`
})
class GreeterComponent {}
@Component
<greeter></greeter>
import {Component} from '@angular/core';
@Component({
selector: 'greeter',
styles: [`
.message {
color: red;
}
`],
template: `<h1 class="message">Hello !</h1>`
})
class GreeterComponent {}
Styles
<greeter></greeter>
ngContent
import {Component, Input} from '@angular/core';
@Component({
selector: 'tab',
template: `<section class="tab">
<h1>This is a Tab</h1>
<!-- Le contenu de la balise <tab> sera inséré ici -->
<ng-content></ng-content>
</section>`
})
export class TabComponent {}
<tab>
<h2>Tab Content</h2>
</tab>
Lifecycle Hooks
@Component(...)
export class MyComponent {
constructor() { }
ngOnInit() {}
ngOnDestroy() {}
ngDoCheck() {}
ngOnChanges(records) {}
ngAfterContentInit() {}
ngAfterContentChecked() {}
ngAfterViewInit() {}
ngAfterViewChecked() {}
}
Callback appelés à différents moments de la vie du component.
Bonnes pratiques
import {Component, OnInit} from '@angular/core'
@Component()
export class myComponent implements OnInit{
constructor() { /* Injection de dépendance */ }
ngOnInit() { /* code à executer à l'initialisation */ }
}
Utiliser les interfaces !!!
Au lieu de charger le constructeur pour rien, privilégier l'utilisation de ngOnInit()
Manipule le DOM pour ajouter ou supprimer des éléments (NgIf, NgFor...)
On utilise le préfixe "*" (astérisque)
<p *ngIf="condition">
condition is true and ngIf is true.
</p>
Directives Structurelles
ngIf
<div *ngIf="false"></div>
<div *ngIf="a > b"></div>
<div *ngIf="str == 'yes'"></div>
<div *ngIf="myFunc()"></div>
Permet d'afficher un élément selon la valeur d'une expression booléenne.
Une alternative consiste à utiliser :
<div [hidden]="someProp">I am hidden</div>
ngSwitch
<div *ngIf="myVar == 'A'">Var is A</div>
<div *ngIf="myVar == 'B'">Var is B</div>
<div *ngIF="myVar == 'C'">Var is C</div>
<div *ngIf="myVar != 'A' && myVar != 'B' && myVar != 'C'"></div>
<div [ngSwitch]="myVar">
<div *ngSwitchCase="A">Var is A</div>
<div *ngSwitchCase="B">Var is B</div>
<div *ngSwitchCase="C">Var is C</div>
<div *ngSwitchDefault>Var is something else</div>
</div>
ngFor
import {Component} from '@angular/core'
@Component({
selector: 'todo-list',
template: `
<h2>Todos</h2>
<ul>
<li *ngFor="let todo of todos">{{todo}}</li>
</ul>
`
})
export class TodoList {
todos = ['Walk the dog', 'Stay in bed', 'Code more']
}
ngFor : index
import {Component} from '@angular/core'
@Component({
selector: 'todo-list',
template: `
<h2>Todos</h2>
<ul>
<li *ngFor="let todo of todos; let i = index">
{{i}} : {{todo}}
</li>
</ul>
`
})
export class TodoList {
todos = ['Walk the dog', 'Stay in bed', 'Code more']
}
Binding
RootComp
ChildComp1
ChildComp1
[property]="expression"
(event)="update()"
@Input()
@Output()
Property Binding
<div [style.color]="'red'">I'm red !</div>
Accès à toutes les propriétés des éléments du DOM :
@Input()
Même syntaxe pour les composants custom :
<greeter [name]="'John'"></greeter>
@Input()
import {Component, Input} from '@angular/core'
@Component({
selector: 'greeter',
template: `<h1>Hello, {{ name }} !</h1>`
})
export class GreeterComponent {
@Input() name: string;
}
<greeter [name]="'John'"></greeter>
Event Binding
<button (click)="doSomething()">Click Me</button>
Accès à tous les évènements natifs du DOM :
@Output()
Même syntaxe pour les composants Angular :
<greeter (greet)="doSomething()"></greeter>
@Output()
import {Component, Output, EventEmitter} from '@angular/core'
@Component({
selector: 'greeter',
template: `<div (click)="onClick()">
{{message}}
</div>`
})
export class GreeterComponent {
message = 'Hello !'
@Output() greet = new EventEmitter<string>();
onClick() {
this.greet.emit(this.message);
}
}
<greeter (greet)="doSomething($event)"></greeter>
import {NgModule} from '@angular/core'
import {CommonModule} from '@angular/common'
import {GreeterComponent} from './greeter.component'
@NgModule({
imports: [CommonModule],
declarations: [GreeterComponent],
exports: [GreeterComponent]
})
export class GreeterModule {
}
@NgModule
Pipes
{{ collectionOfUsers | orderBy:'firstName' | limitTo:5 }}
Declaration
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'uppercase'
})
export class UpperCasePipe implements PipeTransform {
transform(value: String, args: any[]) {
return value.toUpperCase();
}
}
Utilisation
import {Component, View} from '@angular/core';
import {UpperCasePipe} from './UpperCasePipe'
@Component({
selector: 'widget1',
template: `<div>{{'Va passer dans le pipe' | uppercase}}</div>`
})
export class Widget1{}
@NgModule({
declarations: [Widget1, UpperCasePipe],
exports: [Widget1]
})
@Injectable
import {Injectable} from '@angular/core'
@Injectable()
export class GreeterService {
greet(name: string): string {
return `Hello, ${name} !`
}
}
import {NgModule} from '@angular/core'
import {GreeterService} from './greeter.service'
@NgModule({
providers: [GreeterService]
})
export class GreeterModule {
}
RxJS
Angular 4.1.3
By AdapTeach
Angular 4.1.3
- 1,352