> For the complete documentation index, see [llms.txt](https://guide-angular.wishtack.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide-angular.wishtack.io/angular/interaction-entre-composants/output.md).

# Output

## 1. Event Binding

De la même façon que les [Inputs](/angular/interaction-entre-composants/input.md) 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](/angular/composants/event-binding.md) utilisé précédemment pour capturer des événements natifs.

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

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

{% tabs %}
{% tab title="Sous le capot" %}

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

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Remarquez la similarité avec l'[Event Binding](/angular/composants/event-binding.md) sur des événements DOM.

```markup
<button (click)="buy()">BUY</button>
<div (drop)="onDrop($event)"></div>
```

```typescript
button.addEventListener('click', () => this.buy());
div.addEventListener('drop', (dropEvent) => this.onDrop(dropEvent));
```

{% endhint %}

{% hint style="warning" %}
Contrairement aux [Inputs](/angular/interaction-entre-composants/input.md), 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é.
{% endhint %}

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

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

{% tabs %}
{% tab title="book-preview\.component.ts" %}

```typescript
...
export class BookPreviewComponent {
    rate;
}
```

{% endtab %}
{% endtabs %}

... il ne se passe rien mais par analogie avec les [Inputs](/angular/interaction-entre-composants/input.md), il faut ajouter le décorateur `@Output()` :

{% tabs %}
{% tab title="book-preview\.component.ts" %}

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

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

{% endtab %}
{% endtabs %}

... 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](/angular/composants/event-binding.md), 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)*.

{% tabs %}
{% tab title="book-preview\.component.ts" %}

```typescript
export class BookPreviewComponent {
    @Output() rate = new EventEmitter();
}
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
`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.

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

{% endhint %}

{% hint style="danger" %}
Faites attention à bien importer la bonne classe `EventEmitter`.
{% endhint %}

![Attention à bien importer le bon \`EventEmitter\`](/files/-LBM-N14JCutx2Bf6U-0)

## 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`.

{% tabs %}
{% tab title="book-preview\.component.ts" %}

```typescript
export class BookPreviewComponent {

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

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

}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="book-preview\.component.html" %}

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

{% endtab %}
{% endtabs %}

![](/files/-LAxnw5Wn1pqFyDVtMnj)
