# Model Input : Un aperçu approfondi

Dans notre précédent [article](https://angulardev.fr/signal-input-comment-ca-marche), nous avons vu ensemble ce qu'est un `Signal Input` et comment l'utiliser. Nous avons particulièrement remarqué sa similarité avec le décorateur `@Input()`.

Dans ce nouvel article, nous verrons ensemble un nouveau type de input qui est toujours basé sur `Angular Signal`. Ce nouveau type de input a été conçu de façon très ingénieuse et est aussi très similaire à une fonctionnalité existante de Angular qui est très utilisée. Découvrons-le ensemble sans plus attendre !

### Qu'est-ce qu'un `Model Input` en Angular ?

En nous basant sur la documentation de Angular, un `Model Input` est **un type spécial d'input qui permet à un composant A de propager de nouvelles valeurs vers un composant B.** En effet, lorsqu'on analyse cette définition, ce qui nous vient à l'esprit c'est qu'un `Model Input` fait la même chose qu'un `Signal Input` dans le fonctionnement comme l'indique cet exemple :

```typescript
import {Component, model, input} from '@angular/core';
@Component({...})
export class CustomCheckbox {
  // This is a model input.
  checked = model(false);

  // This is a standard input.
  disabled = input(false);
}

<!--- Parent component side --->
<custom-checkbox [checked]="true" [disabled]="false" />
```

Le code ci-dessus nous démontre que les deux types d'input à savoir `Signal Input` et `Model Input` permettent de faire le `one-way binding` c'est-à-dire dans notre cas ici **la communication unidirectionnelle d'un composant parent vers un composant enfant** et non l'inverse.

Cependant, le `Model Input` ne se limite pas à cela. Dans sa philosophie de propager de nouvelles valeurs, le `Model Input` est **également accessible en écriture contrairement à un** `Signal Input`. Nous pouvons donc modifier la valeur d'un `Model Input` depuis le composant enfant où il a été instancié ce qui n'est pas le cas du `Signal Input` qui est `read-only`. Voici une illustration :

```typescript
import {Component, model, input} from '@angular/core';
@Component({
  selector: 'custom-checkbox',
  template: '<div (click)="toggle()"> ... </div>',
})
export class CustomCheckbox {
  checked = model(false);
  disabled = input(false);

  toggle() {
    // While standard inputs are read-only, you can write directly to model inputs.
    this.checked.set(!this.checked());
  }
}
```

Dans l'illustration de code ci-dessus, nous remarquons l'utilisation de la méthode `set()` sur notre `Model Input`. Nous pouvons en déduire que la méthode `update()` aussi peut être utilisée et pour conclure que notre `Model Input` est un `WritableSignal`.

Pour finir, en nous basant sur les deux extraits de code précédent, on peut facilement émettre l'hypothèse suivante :

> ***Lorsque le composant parent ou enfant (peu importe l'un des deux) écrit une nouvelle valeur dans le Model Input, Angular peut propager cette nouvelle valeur vers le composant qui lie cette valeur.***

En effet, c'est typiquement le fonctionnement du `Model Input`. **Il ne permet pas que la liaison unidirectionnelle (**`one-way binding`**) mais également la liaison bidirectionnelle (**`two-way binding`**)**. Tout ceci nous fait penser à `ngModel` que nous utilisons déjà énormément dans Angular.

### `Two-way binding` avec `Model Input`

La documentation de Angular nous présente deux situations différentes pour l'utilisation du `two-way binding` en se basant sur `Angular Signal` ou sur du `JS/TS` classique.

* `Two-way binding` avec du `JS/TS` classique :
    

```typescript
@Component({
  ...,
  // `checked` is a model input.
  // The parenthesis-inside-square-brackets syntax (aka "banana-in-a-box") creates a two-way binding
  template: '<custom-checkbox [(checked)]="isAdmin" />',
})

export class UserProfile {
  protected isAdmin = false;
}
```

Dans l'exemple ci-dessus, le composant `CustomCheckbox` peut écrire des valeurs dans `checked`, qui propage ensuite ces valeurs vers la propriété `isAdmin` dans `UserProfile`. Cette liaison permet de synchroniser les valeurs de `checked` et de `isAdmin`.

* `Two-way binding` avec `Angular Signal` :
    

```typescript
@Component({
  ...,
  // `checked` is a model input.
  // The parenthesis-inside-square-brackets syntax (aka "banana-in-a-box") creates a two-way binding
  template: '<custom-checkbox [(checked)]="isAdmin" />',
})

export class UserProfile {
  protected isAdmin = signal(false);
}
```

Dans cet exemple ci-dessus, le `CustomCheckbox` peut écrire des valeurs dans `checked`, qui propage ensuite ces valeurs vers `isAdmin` dans `UserProfile`. Cette liaison permet de synchroniser les valeurs de `checked` et de `isAdmin`. Cependant, il est très important de noter qu'ici, ***la liaison transmet le signal*** `isAdmin` ***lui-même, et non la valeur du signal.***

Pour finir, en nous basant sur le principe du `two-way binding`, lorsque nous déclarons un `Model Input` dans un composant ou une directive, Angular crée automatiquement un `event` correspondant. Voici un exemple :

```typescript
@Directive({...})
export class CustomCheckbox {
  // This automatically creates an output named "checkedChange".
  // Can be subscribed to using `(checkedChange)="handler()"` in the template.
  checked = model(false);
}
```

Angular émet cet `event` de changement chaque fois que nous écrivons une nouvelle valeur dans le `Model Input` en appelant les méthodes `set()` ou `update()`.

### Différences entre `model()` et `input()`

Nous avons commencé cet article en essayant de voir la similarité entre un `Signal Input` et un `Model Input`. A présent, nous verrons les éléments qui les différencient :

* `model()` définit à la fois un `input` et un `output`. Le nom de l'`output` est toujours le nom de l'`input` suffixé par `Change` pour prendre en charge les liaisons bidirectionnelles. C'est au composant qui l'implémente de décider s'il veut utiliser seulement l'`input`, seulement l'`output`, ou les deux.
    
* `ModelSignal` est un `WritableSignal`, ce qui signifie que sa valeur peut être modifiée de n'importe où à l'aide des méthodes `set()` et `update()`. Lorsqu'une nouvelle valeur est attribuée, le `ModelSignal` émet un `output`. Il en va différemment de l'`InputSignal`, qui est en `read-only`.
    
* Les `Model Inputs` ne prennent pas en charge `transform`, contrairement aux `Signal Inputs`.
    

En somme, dans cet article, l'objectif a été de vulgariser le concept de `Model Input`. Bien qu'ayant une similarité avec le `Signal Input`, nous avons remarqué qu'il est beaucoup plus proche de la philosophie autour du `ngModel` à travers le `two-way binding` mais basé sur `Angular Signal`. Toutefois, il faut noter que `Model Input` est toujours ***Developer Preview***.

> Pour plus d'informations 👉 [Model Inputs](https://angular.dev/guide/signals/model#two-way-binding-with-signals)
