Angular 7: обнаружение асинхронного валидатора - PullRequest
2 голосов
/ 11 марта 2019

Я написал асинхронный валидатор, чтобы проверить, существует ли введенный адрес электронной почты в моей базе данных.

Я использую api реактивной формы для создания своей формы, и я настроил свой асинхронный валидатор только для запуска«размытие».Как упомянуто в угловой документации

, она работает хорошо: проверка запускается, когда я покидаю поле, НО сообщение об ошибке не отображается, пока я не взаимодействую со своей формой.

Если я запускаю changeDetection вручную с помощью функции setTimeout в моей проверке, это работает.

Любая идея, почему эта ошибка не отображается сразу после завершения проверки?

Вот мое определение формы:

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: ['']
  })
}

И мой метод проверки:

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)
    );
  }
};

и часть шаблона:

<mat-form-field fxFlex="60">
  <mat-placeholder>
    <mat-icon>email</mat-icon>
    <span> Email</span>
  </mat-placeholder>
  <input matInput formControlName="email">
  <mat-error *ngIf="email.hasError('emailAlreadyUserByStudent')">
    Email déjà utilisé.
  </mat-error>
  <span *ngIf="email.pending">Validating...</span>
</mat-form-field>

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

В качестве обходного пути (я до сих пор не уверен, что это лучший способ сделать это, потому что в примерах кода это не требуется ...), я добавил ручное обнаружение изменений в конце моей функции валидатора:

  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))
  );
}

};

0 голосов
/ 11 марта 2019

Попробуйте сделать это:

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

constructor(
  changeDetectorRef: ChangeDetectorRef
) {
  //call this when you receive the backend response
  changeDetectorRef.markForCheck();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...