Cours Angular · Module 8: Formulaires

FormArray - Champs dynamiques

2 min de lecture

FormArray permet d'ajouter et de supprimer des champs de façon dynamique - comme ajouter de nouvelles techniques à l'arsenal d'un samouraï !

1import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
2
3interface SkillForm {
4  name: FormControl<string>;
5  level: FormControl<number>;
6}
7
8@Component({
9  template: `
10    <form [formGroup]="samuraiForm" (ngSubmit)="onSubmit()">
11      <input formControlName="name" placeholder="Samurai name">
12
13      <h3>Skills</h3>
14      <div formArrayName="skills">
15        @for (skill of skills.controls; track $index; let i = $index) {
16          <div [formGroupName]="i" class="skill-row">
17            <input formControlName="name" placeholder="Skill name">
18            <input formControlName="level" type="number" placeholder="Level">
19            <button type="button" (click)="removeSkill(i)">×</button>
20          </div>
21        }
22      </div>
23
24      <button type="button" (click)="addSkill()">Add skill</button>
25
26      <button type="submit">Save</button>
27    </form>
28  `
29})
30export class DynamicFormComponent {
31  private fb = inject(FormBuilder);
32
33  samuraiForm = this.fb.group({
34    name: ['', Validators.required],
35    skills: this.fb.array<FormGroup<SkillForm>>([])
36  });
37
38  // Getter pour un accès simplifié
39  get skills(): FormArray<FormGroup<SkillForm>> {
40    return this.samuraiForm.get('skills') as FormArray;
41  }
42
43  addSkill(): void {
44    const skillGroup = this.fb.group({
45      name: ['', Validators.required],
46      level: [1, [Validators.min(1), Validators.max(10)]]
47    });
48    this.skills.push(skillGroup);
49  }
50
51  removeSkill(index: number): void {
52    this.skills.removeAt(index);
53  }
54
55  onSubmit(): void {
56    if (this.samuraiForm.valid) {
57      console.log(this.samuraiForm.value);
58      // { name: 'Musashi', skills: [{ name: 'Kendo', level: 5 }, ...] }
59    }
60  }
61}

Initialisation avec des données

1loadSamurai(samurai: Samurai): void {
2  // Réinitialise et définit les champs simples
3  this.samuraiForm.patchValue({
4    name: samurai.name
5  });
6
7  // Vide et ajoute les compétences
8  this.skills.clear();
9  samurai.skills.forEach(skill => {
10    this.skills.push(this.fb.group({
11      name: [skill.name, Validators.required],
12      level: [skill.level]
13    }));
14  });
15}

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. À quoi sert FormArray ?

  2. 2. Quelle méthode utilises-tu pour ajouter un nouveau champ à la fin d'un FormArray ?

Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète le formulaire avec une liste dynamique de compétences du samouraï.

  • Tri horizontal

    Ordonne les éléments de l'en-tête de boucle qui itère sur les champs d'un FormArray (une seule ligne) : @for (skill of skills.controls; track $index)

  • Tri vertical

    Ordonne les étapes pour repeupler un FormArray avec les données du samouraï (ordre d'exécution à l'intérieur de la méthode, ligne par ligne).

  • Clique dans l'ordre

    Construis le corps du getter qui renvoie un FormArray : return this.form.get('skills') as FormArray. Clique sur les éléments dans l'ordre.

Articles utiles