Skip to content

Utiliser le service FormBuilder

Voici un exemple de formulaire de connexion qui utilise des propriétés FormControl, la directive formControl et le service FormBuilder :

ts
import { Component } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms';

@Component({
  selector: 'app-login-form',
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <label>
        Email:
        <input type="email" [formControl]="emailControl">
      </label>
      <br>
      <label>
        Mot de passe:
        <input type="password" [formControl]="passwordControl">
      </label>
      <br>
      <button type="submit">Se connecter</button>
    </form>
  `
})
export class LoginFormComponent {
  emailControl = new FormControl('');
  passwordControl = new FormControl('');
  form: FormGroup = this.formBuilder.group({
      email: this.emailControl,
      password: this.passwordControl
  });

  onSubmit() {
    // La soumission du formulaire est gérée ici
  }
}
import { Component } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms';

@Component({
  selector: 'app-login-form',
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <label>
        Email:
        <input type="email" [formControl]="emailControl">
      </label>
      <br>
      <label>
        Mot de passe:
        <input type="password" [formControl]="passwordControl">
      </label>
      <br>
      <button type="submit">Se connecter</button>
    </form>
  `
})
export class LoginFormComponent {
  emailControl = new FormControl('');
  passwordControl = new FormControl('');
  form: FormGroup = this.formBuilder.group({
      email: this.emailControl,
      password: this.passwordControl
  });

  onSubmit() {
    // La soumission du formulaire est gérée ici
  }
}

Dans ce code, nous avons créé deux propriétés FormControl indépendantes : emailControl et passwordControl. Nous avons ensuite utilisé la directive formControl pour lier chaque champ de formulaire à un contrôle FormControl respectif. Enfin, nous avons utilisé le service FormBuilder pour créer un objet FormGroup à partir de ces contrôles et l'avons lié au formulaire en utilisant la directive formGroup.

Quelle est l’intérêt d'utiliser le service FormBuilder ?

En utilisant le service FormBuilder, vous pouvez créer des formulaires complexes de manière simple et concise, sans avoir à gérer manuellement la création et l'ajout de contrôles FormControl à un objet FormGroup. Cela peut être particulièrement utile lorsque vous avez besoin de créer des formulaires avec un grand nombre de champs ou lorsque vous souhaitez ajouter des champs dynamiquement.

ts
import { Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'app-login-form',
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <label>
        Email:
        <input type="email" formControlName="email">
      </label>
      <br>
      <label>
        Mot de passe:
        <input type="password" formControlName="password">
      </label>
      <br>
      <button type="submit">Se connecter</button>
    </form>
  `
})
export class LoginFormComponent {
  form: FormGroup = this.formBuilder.group({
    email: '',
    password: ''
  })

  constructor(private formBuilder: FormBuilder) {}

  onSubmit() {
    // La soumission du formulaire est gérée ici
  }
}
import { Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'app-login-form',
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <label>
        Email:
        <input type="email" formControlName="email">
      </label>
      <br>
      <label>
        Mot de passe:
        <input type="password" formControlName="password">
      </label>
      <br>
      <button type="submit">Se connecter</button>
    </form>
  `
})
export class LoginFormComponent {
  form: FormGroup = this.formBuilder.group({
    email: '',
    password: ''
  })

  constructor(private formBuilder: FormBuilder) {}

  onSubmit() {
    // La soumission du formulaire est gérée ici
  }
}

Dans l'exemple de code, les éléments du tableau des propriétés email et password sont utilisés pour définir la valeur initiale du contrôle et les validateurs associés.

La première valeur du tableau est la valeur initiale du contrôle. Dans l'exemple de code, nous avons défini cette valeur sur une chaîne vide pour le champ de courriel et le champ de mot de passe. Cela signifie que le champ de formulaire correspondant sera vide lorsque le composant sera chargé pour la première fois.

Explications sur la nullité (Angular 14+)

  • Pourquoi "string | null" ?: Dans TypeScript, string | null signifie que la valeur peut être soit une chaîne de caractères (string) soit nulle (null). Lorsque vous réinitialisez un champ de formulaire en Angular, par défaut, il prend la valeur null. C'est pour cette raison que nous incluons null dans notre typage.

  • Option nonNullable : En codant, vous voudrez peut-être vous assurer que certains champs ne deviennent jamais "nuls". Angular v14 a introduit une option pour cela : nonNullable. Lorsque vous utilisez cette option, votre champ ne prendra jamais la valeur null, ce qui peut être pratique pour éviter des erreurs inattendues.

    Exemple :

    typescript
    email: new FormControl<string>('', { validators: Validators.required, nonNullable: true })
    email: new FormControl<string>('', { validators: Validators.required, nonNullable: true })

    Ici, même si vous réinitialisez le champ email, il ne sera jamais null.

  • Utilisation de NonNullableFormBuilder :

C'est une nouvelle fonctionnalité d'Angular v14 qui vous permet de créer facilement des formulaires où les champs ne peuvent pas être "nuls". Au lieu d'ajouter l'option nonNullable à chaque champ, vous pouvez utiliser NonNullableFormBuilder.

typescript
form = this.formBuilder.nonNullable.group({
  email: ['', Validators.required],
  password: ['', Validators.required]
});
form = this.formBuilder.nonNullable.group({
  email: ['', Validators.required],
  password: ['', Validators.required]
});

Si vous n'aimez pas taper fb.nonNullable à chaque fois, il y a un raccourci ! Vous pouvez simplement utiliser NonNullableFormBuilder à la place de FormBuilder.

typescript
constructor(private formBuilder: NonNullableFormBuilder) {}
constructor(private formBuilder: NonNullableFormBuilder) {}