Retour au cours

Gérer les validateurs asynchrones

Le Développeur Angular Complet : de Zéro à Héros

49. Gérer les validateurs asynchrones

Les validateurs asynchrones sont nécessaires lorsque la validation nécessite un appel backend (ex : vérifier si un nom d'utilisateur est déjà pris dans la base de données). Ils s'exécutent après que tous les validateurs synchrones ont réussi.

Structure d'un validateur asynchrone

Une fonction de validation asynchrone renvoie un Observable ou une Promise de ValidationErrors | null.

Exemple : Validateur d'unicité du nom d'utilisateur

Ce validateur interroge le backend via un service injecté.

typescript // unique-username.validator.ts import { AbstractControl, ValidationErrors, AsyncValidatorFn } from '@angular/forms'; import { Observable, timer } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { UserService } from './user.service';

export function uniqueUsernameValidator(userService: UserService): AsyncValidatorFn { return (control: AbstractControl): Observable<ValidationErrors | null> => { // 1. Attendre 500ms avant de vérifier pour réduire les appels API (Debounce) return timer(500).pipe( switchMap(() => { if (!control.value) { return of(null); }

    // 2. Appeler le service (qui renvoie un Observable)
    return userService.checkUsernameExists(control.value).pipe(
      map(exists => {
        // 3. Renvoyer l'erreur si l'utilisateur existe, sinon null
        return exists ? { uniqueUsername: true } : null;
      })
    );
  })
);

}; }

Appliquer le validateur asynchrone

Les validateurs asynchrones sont passés comme troisième argument au constructeur FormControl.

typescript // Dans le composant : constructor(private fb: FormBuilder, private userService: UserService) { this.registerForm = this.fb.group({ username: ['', [Validators.required], // Validateurs synchro (2ème argument) [uniqueUsernameValidator(this.userService)] // Validateurs asynchro (3ème argument) ] }); }

Pendant l'exécution de la validation asynchrone, l'état du contrôle sera pending.