4 votes

Angular 7 : Détection des modifications du validateur asynchrone

J'ai écrit un validateur asynchrone pour vérifier si l'e-mail saisi existe déjà dans ma base de données.

J'utilise l'API de formulaire réactif pour construire mon formulaire et j'ai configuré mon validateur asynchrone pour se déclencher uniquement sur "blur". Comme mentionné dans la documentation d'angular

ça fonctionne bien: la validation est déclenchée lorsque je quitte le champ MAIS le message d'erreur n'est pas affiché jusqu'à ce que j'interagisse avec mon formulaire.

Si je déclenche manuellement la détection des modifications avec une fonction setTimeout dans ma validation, ça fonctionne.

Une idée pourquoi cette erreur n'est pas affichée immédiatement après la validation?

Voici la définition de mon formulaire :

private initPersonalInformationFormGroup() {
  this.personalInformationFormGroup = this._formBuilder.group({
    lastName: ['', Validators.required],
    firstName: ['', Validators.required],
    gender: [Gender.MALE],
    birthDate: [''],
    birthPlace: [''],
    nationality: [''],
    inss: ['', [Validators.minLength(11), Validators.maxLength(11), Validators.pattern('[0-9]{11}')]],
    email: ['', {
      validators: [Validators.required, Validators.email],
      asyncValidators: [this._studentEmailValidator()],
      updateOn: 'blur'
    }],
    phoneNumber: [null, Validators.pattern('\\+32[1-9][0-9]{7,8}')],
    address: this._formBuilder.group({
      street: ['', [Validators.maxLength(60)]],
      houseNumber: ['', [Validators.maxLength(10)]],
      city: ['', [Validators.maxLength(60)]],
      postalCode: [null, [Validators.min(1000), Validators.max(9999)]],
    }, {
      validators: this._completeAddressValidator()
    }),
    previousSchool: ['', Validators.maxLength(60)],
    additionalInformation: ['']
  })
}

Et ma méthode de validation :

private _studentEmailValidator(): AsyncValidatorFn {
  return (control: FormGroup): Observable<{ [key: string]: any } | null> => {
    const email = control.value;
    // setTimeout(() => this._checkDetectorRef.detectChanges(), 5000);
    return this._adminFacade.checkStudentWithEmailExists(email).pipe(
      take(1),
      map(exists => exists ? {'emailAlreadyUserByStudent': {value: email}} : null),
      catchError(() => null)
    );
  }
};

et la partie du modèle :

    email
     Email

    Email déjà utilisé.

  Validation en cours...

4voto

Stéphane Points 444

En tant que solution de contournement (je ne suis toujours pas sûr que c'est la meilleure façon de le faire car ce n'est pas nécessaire dans les exemples de code..), j'ai ajouté un manual detectChanges à la fin de ma fonction de validation :

  private _studentEmailValidator(): AsyncValidatorFn {
return (control: FormGroup): Observable<{ [key: string]: any } | null> => {
  const email = control.value;
  return this._adminFacade.checkStudentWithEmailExists(email).pipe(
    take(1),
    map(exists => exists ? {'emailAlreadyUserByStudent': {value: email}} : null),
    catchError(() => null),
    tap(() => setTimeout(() => this._checkDetectorRef.detectChanges(), 0))
  );
}

};

-1voto

Leandro Lima Points 878

Essayez de faire cela:

import { ChangeDetectorRef } from '@angular/core';

constructor(
  changeDetectorRef: ChangeDetectorRef
) {
  //appelez ceci lorsque vous recevez la réponse du backend
  changeDetectorRef.markForCheck();
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X