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