Angular ValidatorFn returns,但不阻塞Form

Angular ValidatorFn returns, but does not block Form

我已经为我的表单构建了一个自定义验证器,returns 需要 ValidationErrors 对象。

ValidateDirectory(clientId: string): ValidatorFn {
        return (control: AbstractControl): ValidationErrors | null => {
            const ret: ValidationErrors = { isValidDirectory: true };
            if (control.value == null || control.value === '') {
                return ret;
            }
            this.service.getList(clientId, control.value).subscribe((res) => {
                if (res.technicalRetCode !== 0) {
                    console.log(ret);
                    return ret;
                }
                return null;
            });
            return null;
        };
    }

我用 console.log 行证明了这一点,这实际上记录了我的对象。

验证器附加在 ngOnInit

中的 Validators.required 之外
ngOnInit() {
  ...
  this.fourthFormGroup = this._formBuilder.group({
      dateipfad: ['', {validator: Validators.compose([Validators.required, this.directoryValidator.ValidateDirectory(this.clientID)]), updateOn: 'blur'}]
    });
  ... 
}

问题是:所需的验证器按预期工作,但我的自定义验证器只是记录。

我已经尝试了很多,比如使用 validators 数组而不是 Validators.compose,调整我的验证器方法来设置 control.setErrors(ret) 一些其他的东西,但没有任何效果。

我觉得有一个很简单的解决方案,但我就是找不到...

编辑 1: 我创建了一个 stackblitz https://stackblitz.com/edit/angular-ysyb9i?file=src%2Fapp%2Fapp.component.html

解释:输入接受任何字符串,取消选择验证开始。 如果输入是 'false' 它应该通过返回 const ret: ValidationErrors = { isValidDirectory: true }; 将输入设置为无效,任何其他字符串应该是有效的并且它 returns null.

两个结果都记录在控制台上,所以你可以检查它。如果输入无效,它应该在下方显示通知 div(不太确定,只是添加它以供此 stackblitz 显示)

如果您的验证器中的代码是异步的,您应该使用异步验证器。

this.fourthFormGroup = this._formBuilder.group({
  dateipfad: ['', {
    validators: [Validators.required],
    asyncValidators: [this.directoryValidator.ValidateDirectory(this.clientID)],
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                    put it here
    updateOn: 'blur'
  }]
});

验证器应该 return AsyncValidatorFn 接口,您应该在其中订阅 observable 而不是映射到您想要的值。 Angular 将自动订阅您的 observable。

ValidateDirectory(clientId: string): AsyncValidatorFn {
  return (control: AbstractControl): 
             Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
    const ret: ValidationErrors = { isValidDirectory: true };

    if (control.value == null || control.value === '') {
      return of(ret);
    }

    return this.service.getList(clientId, control.value).pipe(map((res: any) => {
      if (res.technicalRetCode !== 0) {
        return ret;
      }

      return null;
    }));
  };
}

Forked Stackblitz

另请注意,异步验证器仅在所有同步验证器 return 为 null 时才会触发。所以你不会从一开始就看到错误,因为你有同步 required 验证器。