# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://guide-angular.wishtack.io/angular/interaction-entre-composants/output.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
