【问题标题】:Reactive Form Async Validator is not setting the error to the FormGroup反应式表单异步验证器未将错误设置为 FormGroup
【发布时间】:2020-11-02 14:18:58
【问题描述】:

我正在使用一个简单的表单在 Angular 10 中做一个 Web 应用程序来接收两个值,我将在后端验证它们,执行 HTTP 调用。为此,我创建了一个运行完美的异步验证器。

问题: 它没有将错误设置为 FormGroup。换言之,FormGroup 始终有效。

this.form = this.fb.group({
  // I will validate this two values with the backend
  patientIdentifications: this.fb.group({
    clinicRecord: [null, Validators.required],
    documentId: [null, Validators.required]
  }, {
    updateOn: 'blur',
    asyncValidators: CustomValidators.isPatientValid(this.myService) // <= async validator
  }),
  // Just to illustrate that I have more FormControls
  firstName: [null, Validators.required],
});

异步验证器

export class CustomValidators {

  static isPatientValid(myService: MyService): AsyncValidatorFn {
    return (formGroup: FormGroup):
      Promise<ValidationErrors | null> |
      Observable<ValidationErrors | null> => {

      const clinicRecordControl = formGroup.controls.clinicRecord;
      const documentIdControl = formGroup.controls.documentId;
      const clinicRecordValue = clinicRecordControl.value;
      const documentIdValue = documentIdControl.value;

        return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
          map(patient => patient ? of(null) : of({valid: true})),
          catchError(() => of(null))
        );
    };
  }

}

当两个输入失去焦点时,HTTP 调用完美完成。但是FormGroup中没有设置错误。

我尝试了以下解决方案:

#1。在验证器调用中添加bind()

patientIdentifications: this.fb.group({
        clinicRecord: [null, Validators.required],
        documentId: [null, Validators.required]
      }, {
        updateOn: 'blur',
        asyncValidators: CustomValidators.isPatientValid(this.myService).bind(this) // <= bind
      }),

#2。去掉of函数

return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
              map(patient => patient ? null : {valid: true}), // <= remove the "of"
              catchError(() => of(null))
            );

#3。直接使用FormGroup的实例设置错误

return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
              map(patient => patient ? formGroup.setErrors(null) : formGroup.setErrors({valid: true})),
              catchError(() => of(null))
            );

没有一个解决方案对我有用。

我的目标是正确设置 FormGroup 的错误,使 FormGroup 为 INVALID,这是正确的做法。

【问题讨论】:

  • 不应该catchError(() =&gt; of(null))返回of({valid: true}),因为这是一个错误?
  • 也可以尝试将map 换成switchMap
  • @Chrillewoodz 你的意思是做return formGroup.valueChanges.pipe(switchMap... 还是直接返回switchMap
  • return myService.getPatient(clinicRecordValue, documentIdValue).pipe( switchMap(patient =&gt; patient ? of(null) : of({valid: true})), catchError(() =&gt; of(null)) );
  • @Chrillewoodz 信不信由你,你的第一条评论解决了我的问题,我需要在catchError 中返回of({valid: true})。此外,它适用于switchMapmap,尽管我不明白其中的区别。我知道switchMap 是干什么用的,但从未见过它被这样使用过。最后,我不确定正确的做法是of(null) 还是formGroup.setErrors(null)。如果你能用最好的方法给出答案,我会接受。

标签: angular angular-reactive-forms


【解决方案1】:

现在您说错误是可以的,因为您没有返回of({valid: true}),而是返回of(null)。如果您将其更改为此,它将起作用:

return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
      map(patient => patient ? of(null) : of({valid: true})),
      catchError(() => of({valid: true))
    );
};

根据您询问是返回 observable 还是使用 formGroup.setErrors(null) 的评论,我会选择 observable,因为在查看 the docs for custom validators 时,这似乎是推荐的方式。这与您何时使用异步或同步验证器无关。

【讨论】:

    猜你喜欢
    • 2021-02-15
    • 1970-01-01
    • 2020-09-07
    • 1970-01-01
    • 2020-05-01
    • 2019-01-25
    • 1970-01-01
    • 2020-04-06
    • 2020-01-17
    相关资源
    最近更新 更多