Model Input : Un aperçu approfondi

Search for a command to run...

No comments yet. Be the first to comment.
Dans notre précédent article Angular Signals : que faut-il retenir quand je débute ?, nous avons exploré ce qui se cache derrière les Signals en Angular. Aujourd'hui, nous aborderons l'un des concepts liés aux Angular Signals : les Signal Inputs, com...
Depuis l'arrivée des Signals dans Angular, une question revient sans cesse dans les équipes : comment continuer à profiter de la puissance de RxJS, de ses opérateurs, de sa gestion fine des flux async

Si vous suivez l'actualité d'Angular avec la sortie de la version 20 du framework, vous avez probablement entendu de plus en plus ce terme. Mais au-delà du jargon, qu'est-ce que le Zoneless concrètement pour vos applications Angular ? Pourquoi est-il...

Si vous avez l’habitude de manipuler des formulaires réactifs (Reactive Forms) dans un projet Angular, vous connaissez certainement la méthode patchValue(…). Cette méthode, permet de mettre à jour les valeurs de votre formulaire. Cependant, son utili...

Depuis la sortie de la version 17 du framework Angular, on parle de la renaissance de Angular. Il y a eu beaucoup de changements majeurs depuis la version 16 du framework pour préparer le terrain à cette renaissance. Ces changements majeurs ont rendu...

Dans notre précédent article, 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 !
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 :
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 :
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 InputLa 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 :@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 :@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 :
@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().
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