formArray.patchValue(...) : attention à son utilisation !

Search for a command to run...

No comments yet. Be the first to comment.
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...

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 inp...

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 utilisation sur un formulaire ayant un contrôle de type FormArray qui n’est rien d’autre qu’un formulaire dynamique, dans lequel vous pouvez ajouter et supprimer des contrôles au moment de l'exécution est très délicate. Dans cet article, nous verrons ensemble, pourquoi faut t-il faire attention à la façon dont nous utilisons patchValue(…) lorsqu’il s’agit d’un formulaire ayant un contrôle de type FormArray.
Avant d’entrer dans le vif du sujet, nous rappellerons, l’utilisation classique de la méthode patchValue(…) sur un formulaire simple. Considérons, le bout de code suivant où nous avons un composant ProfileEditorComponent dans lequel est implémenté un formulaire simple composé de deux champs à savoir firstName et lastName :
import {Component} from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
standalone: true,
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl('')
});
}
Dans l’exemple susmentionné, pour mettre à jour les valeurs de notre formulaire en utilisant patchValue(…), voici ce que nous faisons :
this.profileForm.patchValue({
firstName: 'John',
lastName: 'Doe'
});
Une fois, ce bout de code exécuté, notre formulaire sera mis à jour avec les valeurs John pour le firstName et Doe pour le lastName.
La question qui vient à l’esprit est la suivante ?
Est-ce aussi le cas lorsque nous faisons face à un formulaire qui contient des contrôles de type
FormArray?La meilleure façon de s’en assurer, est de faire l’expérience. Let’s go !
Considérons le code ci-dessous :
import { Component } from '@angular/core';
import { FormBuilder, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-addresses',
template: `
<form [formGroup]="addressesForm">
<div formArrayName="addresses">
<div *ngFor="let address of addresses.controls; let i = index" [formGroupName]="i">
<input type="text" formControlName="road" placeholder="Road">
<input type="text" formControlName="city" placeholder="City">
</div>
<button type="button" (click)="addAddress()">Add an address</button>
</div>
</form>
`
})
export class AddressesComponent {
addressesForm = new FormGroup({
addresses: new FormArray([
new FormGroup({
road: new FormControl(),
city: new FormControl()
})
])
});
public get addressesFormArray() {
return this.addressForm.get('addresses');
}
}
Dans le code ci-dessus, nous avons un formulaire qui contient un contrôle de type FormArray. Supposons, qu’après un traitement, nous voulons mettre à jour les adresses de notre formulaire en utilisant naturellement notre méthode patchValue(…). Voici ce que nous écrirons :
this.addressesFormArray.patchValue([
{
road: '1',
city: 'Paris'
},
{
road: '2',
city: 'Lyon'
},
{
road: '3',
city: 'Marseille'
}
]);
Dans notre exemple, si l’on se confère à la logique de la méthode patchValue(…), normalement, notre formulaire doit être mis à jour avec les valeurs des adresses indiquées.
Malheureusement, je ne suis navré de vous décevoir mais ce n’est pas le cas !
Lorsqu’on se rend sur l’interface web, on se rend compte que c’est uniquement le premier objet du tableau des adresses qui est conservé comme valeur.
Notre méthode
patchValue(…)n’a pas su itérer sur le reste des éléments et c’est là tout le piège !
Pour résoudre ce problème, une gymnastique s’impose à nous lors de l’utilisation de notre méthode patchValue(…). Voici donc comment procéder étape par étape :
Étape 1 : Nettoyer notre FormArray
this.addressesFormArray.clear();
Étape 2 : Recréer une nouvelle instance de notre FormArray
/*
Considérons une variable `myAddresses` qui contient toutes les adresses récupérées
après un appel d'API par exemple
*/
while (this.addressesFormArray.controls.length < myAddresses.length) {
this.addressesFormArray.push(new FormGroup({
road: new FormControl(),
city: new FormControl()
}));
}
Étape 3 : Mettre à jour les valeurs avec patchValue(…)
this.addressesFormArray.patchValue(myAddresses);
En somme, pour appliquer un patchValue(…) sur notre formulaire, il est crucial d’identifier la nature des contrôles. S’agit t-il d’un FormControl classique ou d’un FormArray conduisant à un formulaire complexe ? Suivant, le cas, nous savons aujourd’hui quoi faire.
Pour plus d'informations 👉 Reactive Forms