【问题标题】:Reactive Form Async Validator is not clearing the error in the FormGroup反应式表单异步验证器未清除 FormGroup 中的错误
【发布时间】:2021-02-15 10:23:50
【问题描述】:

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

问题: HTTP 调用成功时,FormGroup 中的错误并没有完全清除。换句话说,FormGroup 总是无效的。

在FormGroup 的errors 对象内部,有两个我不知道的奇怪的东西,isScalarsubscribe。也许这就是问题所在?

我正在展示的行为:

  1. HTTP 调用失败:错误设置正确,状态为无效。一切顺利。
  2. HTTP 调用成功:错误未完全清除,状态为无效。糟糕!

表单组

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(
          // Returning "null" if there is a response to clear the FormGroup's errors.
          map(patient => patient ? of(null) : of({valid: true})),
          catchError(() => of({valid: true}))
        );
    };
  }

}

当两个输入失去焦点时,HTTP 调用完美完成。但即使 HTTP 调用成功,FormGroup 仍保持为 INVALID。

我的目标是在 HTTP 调用成功时正确清除 FormGroup 的错误,以使 FormGroup 为 VALID。

【问题讨论】:

    标签: angular angular-reactive-forms


    【解决方案1】:

    例如我的电子邮件实时存在检查器。给你拐杖。

    // In component
    this.form = new FormGroup({
        // ...
        email: new FormController(
            'email',
            [...],
            [ValidatorsHelper.isEmailExistValidator(this.http)]
        ),
        // ...
    };
    
    
    
    // Async validator
    class ValidatorsHelper {
        // ...
    
        static isEmailExistValidator(http: HttpClient): AsyncValidatorFn {
            return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
                return http.post<boolean>(AUTH_REG_EMAIL, { data: control.value }).pipe(
                    map((result) => result ? null : { exist: true }),
                    catchError(() => {
                        return of({ exist: true });
                    }),
                );
            };
        }
    
        // ...
    }
    

    本质上是:return (formGroup: FormGroup): -> return (control: AbstractControl):

    form.d.ts:

    export declare interface AsyncValidatorFn {
        (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
    }
    

    更新:一位提问的同事错过了他在map 中使用了of(null)of(null) 需要 swtichMap,而普通 null 需要 map。详细信息可以在答案下方的评论中找到。

    【讨论】:

    • 如果函数需要返回 Promise 或 Observable,为什么不返回 of(null)?这是我和您的解决方案之间唯一可以看到的区别。你能解释一下吗?
    • 因为,我使用的是map,而不是switchMap
    • 本质上:如果只是值将被修改,则使用 map 并在返回 observable 或 promise 时使用 switchMap。您只需将 value 设置为 of(null) 返回 observable 即可。所以你必须swichMapmap 中没有 of() 的另一个选项 return null
    • 幸福吗? :D 一切都好吗?
    猜你喜欢
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 2020-01-17
    • 2020-04-06
    相关资源
    最近更新 更多