【问题标题】:validator to return Promise or Observable : Custom async validator : Angular 8返回 Promise 或 Observable 的验证器:自定义异步验证器:Angular 8
【发布时间】:2021-04-25 11:49:35
【问题描述】:

我正在尝试为我的注册表单创建一个自定义异步验证器,用于检查电子邮件是否为有效电子邮件或未使用第三方 API。这是 API 网站的参考链接 -

https://www.zerobounce.net/email-validation-api.html

我正在尝试使用 RxJs debounceTime, distinctUntilChanged 来实现它。在表单控件中,我需要另外两个验证和模式。但我总是收到此错误 - 错误:预期验证器返回 Promise 或 Observable。

我已经搜索了几个示例,但没有任何效果。提前谢谢你。

验证器 -

export class UniqueEmailValidator{
   static createValidator(_ajaxService : AjaxService){
        return (control : AbstractControl) =>{
            const apiKey = environment.emailValidatationKey;
            const baseUrl = 'https://api.zerobounce.net/v2/validate?';
            if(control.valid){
                return control
                .valueChanges
                .pipe(
                    debounceTime(800),
                    distinctUntilChanged(),
                    switchMap((email : string) => _ajaxService.apiCall('', `${baseUrl}api_key=${apiKey}&email=${email}&ip_address=''`, 'GET', true)),
                    map(res => res.json()),
                    map((validationStatus : any) => {
                        if (
                            validationStatus.status == "valid" &&
                            validationStatus.mx_found == "true"
                        ) {
                            return null
                        } else {
                            return { isEmailInvalid : true }
                        }
                    })
                )
            }
        }
    }
}

注册组件 -

this.registration = this._formBuilder.group({
  firstName: new FormControl('', [
    Validators.required,
    Validators.pattern('^[a-z A-Z]+$')
  ]),
  lastName: new FormControl('', [
    Validators.required,
    Validators.pattern('^[a-z A-Z]+$')
  ]),
  email: new FormControl('', [
    Validators.required,
    Validators.pattern('[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\\.[a-z]{2,3}')
  ],UniqueEmailValidator.createValidator(this._ajaxService))
})

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

为什么要从valueChanges Observable 管道验证器 Observable?这没有多大意义,因为验证器在 valueChange 上运行并且它是脏的。并且您还返回所需的 Observable 仅当控件有效时。因此,当同步验证器将控件标记为无效时,此控件不会返回 Observable。我想这就是导致错误的原因。

试试这个方法:

export class UniqueEmailValidator {
  static createValidator(_ajaxService: AjaxService) {
    return (control: AbstractControl) => {
      const apiKey = environment.emailValidatationKey;
      const baseUrl = 'https://api.zerobounce.net/v2/validate?';

      return timer(800).pipe(
        concatMap((email: string) =>
          _ajaxService.apiCall('', `${baseUrl}api_key=${apiKey}&email=${email}&ip_address=''`, 'GET', true)
        ),
        map(res => res.json()),
        map((validationStatus: any) => {
          if (validationStatus.status == 'valid' && validationStatus.mx_found == 'true') {
            return null;
          } else {
            return { isEmailInvalid: true };
          }
        })
      );
    };
  }
}}

我在一个项目中使用与此类似的方法,我必须检查文件系统上的导出路径。我不太确定的一件事是 distinctUntilChanged。不是已经过滤了吗

【讨论】:

    【解决方案2】:

    这就是我最终得到的结果,它解决了我的问题 -

    验证器 -

    export class UniqueEmailValidator {
        static createValidator(_ajaxService: AjaxService) {
            let validatorSubject$ = new Subject();
            let debouncedSubject$ = new Subject<string>();
    
            debouncedSubject$
            .pipe(debounceTime(500), distinctUntilChanged())
            .subscribe((email: string) => {
                const apiKey = environment.emailValidatationKey;
                const baseUrl = 'https://api.zerobounce.net/v2/validate?';
                _ajaxService.apiCall('', `${baseUrl}api_key=${apiKey}&email=${email}&ip_address=''`, 'GET', true).subscribe({
                    next: (validationData : IEmailValidation) => {
                        if (
                            validationData.status == "valid" &&
                            validationData.mx_found == "true" &&
                            (
                              validationData.sub_status == "alias_address" ||
                              validationData.sub_status == ""
                            )
                        ) {
                            return null
                        } else {
                            return { isEmailInvalid : true }
                        }
                    },
                    error: (validationFailed) => {
                        console.log(
                            "Failed to validate the Email Address",
                            validationFailed
                        );
                    },
                });
            });
    
            return (
                control: AbstractControl
            ):
            | Promise<ValidationErrors | null>
            | Observable<ValidationErrors | null> => {
                debouncedSubject$.next(control.value);
                let promise = new Promise<any>((resolve, reject) => {
                  validatorSubject$.subscribe((result) => resolve(result));
                });
                return promise;
            };
        }
    }
    

    组件 TS -

    this.registration = this._formBuilder.group({
      firstName: new FormControl('', [
        Validators.required,
        Validators.pattern('^[a-z A-Z]+$')
      ]),
      lastName: new FormControl('', [
        Validators.required,
        Validators.pattern('^[a-z A-Z]+$')
      ]),
      email: new FormControl('', [
        Validators.required,
        Validators.pattern('[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\\.[a-z]{2,3}')
      ],UniqueEmailValidator.createValidator(this._ajaxService))
    }) 
    

    组件 HTML -

    <div *ngIf="formcontrol.email.errors.isEmailInvalid">
       <p>Use a working E-mail address.</p>
    </div>
    

    【讨论】:

      猜你喜欢
      • 2019-03-15
      • 2019-01-22
      • 2021-11-26
      • 2021-05-01
      • 2018-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      相关资源
      最近更新 更多