Output
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
.Sous le capot
bookPreviewComponent.rate
.subscribe((rating) => {
this.onRate(rating);
});
<button (click)="buy()">BUY</button>
<div (drop)="onDrop($event)"></div>
button.addEventListener('click', () => this.buy());
div.addEventListener('drop', (dropEvent) => this.onDrop(dropEvent));
Contrairement aux Inputs, si l'"output" n'est pas déclaré correctement, Angular ne produira aucune erreur. Dans ce cas, Angular inscrit notre "listener" à un événement DOM qui n'existe pas et qui ne se produit donc jamais ; notre "listener" ne sera alors simplement jamais appelé.
En déclarant simplement la propriété
rate
sur le composant book-preview
:book-preview.component.ts
...
export class BookPreviewComponent {
rate;
}
... il ne se passe rien mais par analogie avec les Inputs, il faut ajouter le décorateur
@Output()
:book-preview.component.ts
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.).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).book-preview.component.ts
export class BookPreviewComponent {
@Output() rate = new EventEmitter();
}
EventEmitter
est une classe générique et il est recommandé de la typer pour éviter d'émettre des valeurs du mauvais type par erreur ou plus simplement pour indiquer à l'utilisateur du composant le type de données émises par l'"Output" dès la première lecture.@Output() rate = new EventEmitter<number>();
Faites attention à bien importer la bonne classe
EventEmitter
.Attention à bien importer le bon `EventEmitter`
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
.book-preview.component.ts
export class BookPreviewComponent {
@Output() rate = new EventEmitter<number>();
iLoveIt() {
this.rate.emit(5);
}
}
book-preview.component.html
<button (click)="iLoveIt()">I LOVE IT</button>
Dernière mise à jour 4yr ago