Angular 11 AsyncValidator 未返回错误

Angular 11 AsyncValidator not returning error

我有一个基本表单,用于检查电子邮件地址是否作为异步验证程序存在。

ngOnInit(): void {
      this.form = new FormGroup({
        email: new FormControl('',
        [
          Validators.required,
          Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$')
         ],
         [
           pendingPortfolioUserRequestValidator(this.portfolioInviteService, this.data.portfolioId)
          ])
      });
  }

异步验证器 pendingPortfolioUserRequestValidator 看起来像这样

export function pendingPortfolioUserRequestValidator(portfolioInviteService: PortfolioInviteService,
  portfolioId: number): AsyncValidatorFn {
  return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
    return portfolioInviteService.checkUserIsPending(portfolioId, control.value).pipe(map((email) => {
      return (email) ? {'pendingUserExists': true} : null;
    }));
  };
}

确定电子邮件是否存在的代码行 (return (email) ? {'pendingUserExists': true} : null;) 被命中,但是当我检查 errors 集合时,它给出 null 作为值.

我也尝试过使用 promise,但似乎没有用。

进一步 reading,并试图查明这一点,我发现了一个 pending 属性。当我检查它的状态时,属性 仍然处于待处理状态,尽管看起来验证已完成。文章的这一部分有助于理解:

Asynchronous validators implement the AsyncValidatorFn and AsyncValidator interfaces. These are very similar to their synchronous counterparts, with the following differences.

  • The validate() functions must return a Promise or an observable,
  • The observable returned must be finite, meaning it must complete at some point. To convert an infinite observable into a finite one, pipe the observable through a filtering operator such as first, last, take, or takeUntil.

我需要添加对 take(1) 的调用,这已经解决了问题。

更新代码:

export function pendingPortfolioUserRequestValidator(portfolioInviteService: PortfolioInviteService,
  portfolioId: number): AsyncValidatorFn {
  return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
    return portfolioInviteService.checkUserIsPending(portfolioId, control.value).pipe(
      take(1),
      map(
      (email: boolean) => {
      return (email) ? {'pendingUserExists': true} : null;
    }));
  };
}