Output

1. Event Binding

De la même façon que les Inputs permettent de communiquer des données à un "child component", ce dernier peut transmettre des données au "parent component" via un mécanisme d'"Output" similaire à l'Event Binding utilisé précédemment pour capturer des événements natifs.

<wt-book-preview (rate)="onRate($event)"></wt-book-preview>

Nous avons inscrits l'expression onRate($event) comme "listener" de l'événement rate.

bookPreviewComponent.rate
    .subscribe((rating) => {
        this.onRate(rating);
    });

Remarquez la similarité avec l'Event Binding sur des événements DOM.

<button (click)="buy()">BUY</button>
<div (drop)="onDrop($event)"></div>
button.addEventListener('click', () => this.buy());
div.addEventListener('drop', (dropEvent) => this.onDrop(dropEvent));

2. Déclaration de la propriété et décorateur @Output()

En déclarant simplement la propriété rate sur le composant book-preview :

...
export class BookPreviewComponent {
    rate;
}

... il ne se passe rien mais par analogie avec les Inputs, il faut ajouter le décorateur @Output() :

import { Output } from '@angular/core';

...
export class BookPreviewComponent {
    @Output() rate;
}

... et nous remarquons alors une erreur très intéressante :

TypeError: Cannot read property 'subscribe' of undefined

Comme indiqué précédemment, avec l'Event Binding, si Angular trouve un "output" du même nom, il ajoute un listener dessus avec la méthode subscribe. On remarque donc qu'Angular s'attend à ce que les "Outputs" soient des objets qui définissent la méthode subscribe (ou alors quelque chose de similaire à des instances d'"Observables". Cf. RxJS.).

3. Initialisation de la propriété avec EventEmitter

Il faut donc initialiser la propriété. Nous pourrions initialiser la propriété avec n'importe quel Observable mais dans la pratique nous utiliserons la classe Angular EventEmitter (qui hérite de la classe Subject d'RxJS qui elle même hérite de la classe Observable d'RxJS).

export class BookPreviewComponent {
    @Output() rate = new EventEmitter();
}
Attention à bien importer le bon `EventEmitter`

4. Emission de valeurs

Comme son nom l'indique, un EventEmitter permet d'émettre des valeurs. Il peut donc être utilisé n'importe où dans la classe BookPreviewComponent pour remonter des valeurs au composant parent via la méthode emit.

export class BookPreviewComponent {

    @Output() rate = new EventEmitter<number>();

    iLoveIt() {
        this.rate.emit(5);
    }

}
<button (click)="iLoveIt()">I LOVE IT</button>

Dernière mise à jour