Angular 5 Debounce Custom Async Validator - PullRequest
       1

Angular 5 Debounce Custom Async Validator

0 голосов
/ 12 октября 2018

Я создал специальный валидатор Async, который использует сервис для проверки электронной почты на сервере.Однако это означает, что сервер поражен каждый раз, когда вводится символ, что не годится.Здесь я проследил несколько ответов, которые мне не удалось получить.

Мой валидатор:

import {FormControl, NG_ASYNC_VALIDATORS, Validator} from 
'@angular/forms';
import { Http } from '@angular/http';
import {Directive, forwardRef} from "@angular/core";
import {ValidateEmailService} from "../services/validate-email.service";
import {UserService} from "../services/user.service";

@Directive({
  selector: '[appEmailValidator]',
  providers: [
    { provide: NG_ASYNC_VALIDATORS, useExisting: forwardRef(() => EmailValidator), multi: true }
  ]
})
export class EmailValidator implements Validator {
  public validateEmailService: ValidateEmailService;

  constructor(
    private _http: Http,
    private _userService: UserService
  ) {
    this.validateEmailService = new ValidateEmailService(this._http, this._userService);
  }

  validate(c: FormControl) {
    return new Promise(resolve => {
      this.validateEmailService.validateEmail(c.value)
        .subscribe((res) => {
          console.log(res);
          if (res.valid) {
            resolve(null);
          } else {
            resolve({
              valid: {
                valid: false
              }
            });
          }
        });
      })
    }
}

Сам по себе работает хорошо, но как только я пытаюсь добавитькакая-то форма отклика на него, в итоге я нарушаю его.

Я пробовал ответить на этот вопрос , и я получаю ошибки по типу Type X is not assignable to type 'Observable<any>' и т. д.

Я подошел ближе, используя setTimeout, но все, что в итоге закончилось, - остановка функциональности.

Моя конечная цель - запускать валидатор только тогда, когда ввод не изменялся в течение примерно 600 мс, но согласился бы только на проверку каждые 600-2000 мс.

Для дополнительной ясности, метод validateEmail из ValidateEmailService:

public validateEmail(email: string) {

  let validateEmail = new ValidateEmail(email);

  return this._http.get(
    this.getUrl(validateEmail),
    this.getOptionArgs())
    .map((response: Response) => Object.assign(new UserEmailVerification(), response.json().UserEmailVerification));

}

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Вы можете создать Observable в своем обещании, чтобы выполнить дебад.

Эта логика не может быть вырезана и вставлена, но должна приблизить вас.

import {distinctUntilChanged, debounceTime, switchMap} from 'rxjs/operators';

 validate(c: FormControl) {
  return new Promise(resolve => {
    new Observable(observer => observer.next(c.value)).pipe(
      debounceTime(600),
      distinctUntilChanged(),
      switchMap((value) => { return this.validateEmailService.validateEmail(value) })
    ).subscribe(
      (res) => {
        console.log(res);
        if (res.valid) {
          resolve(null);
        } else {
          resolve({
            valid: {
              valid: false
            }
          });
        }
      }
    )
  })
}
0 голосов
/ 12 октября 2018

Я не видел асинхронного валидатора, реализованного как директива, а скорее как функция валидатора, назначенная элементу управления формы.

Вот пример валидатора, который я использую для аналогичного случая:

import { Injectable } from '@angular/core';
import { AbstractControl, AsyncValidatorFn } from '@angular/forms';
import { Observable, timer, of } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';

import { MembershipsService } from '@app/memberships/memberships.service';

@Injectable()
export class MembershipsValidators {

  constructor (
    private membershipsService: MembershipsService,
  ) {}

  checkMembershipExists(email?: string): AsyncValidatorFn {
    return (control: AbstractControl): Observable<{ [key: string]: any } | null> => {
      if (control.value === null || control.value.length === 0) {
        return of(null);
      }
      else if (email && email === control.value) {
        return of(null);
      }
      else {
        return timer(500).pipe(
          switchMap(() => {
            return this.membershipsService.lookupMember(control.value).pipe(
              map(member => {
                if (!member) {
                  return { noMembership: { value: control.value } };
                }

                return null;
              })
            );
          })
        );
      }
    };
  }

}

Это импортируется и применяется к элементу управления формы следующим образом:

this.form = this.formBuilder.group({
  memberEmail: new FormControl('', {
    validators: [ Validators.required, Validators.pattern(regexPatterns.email) ],
    asyncValidators: [ this.membershipsValidators.checkMembershipExists() ],
  }),
});

Таким образом, асинхронный валидатор не срабатывает, пока не будут выполнены синхронные валидаторы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...