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;
}));
};
}
另请注意,异步验证器仅在所有同步验证器 return 为 null 时才会触发。所以你不会从一开始就看到错误,因为你有同步 required
验证器。
我已经为我的表单构建了一个自定义验证器,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
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;
}));
};
}
另请注意,异步验证器仅在所有同步验证器 return 为 null 时才会触发。所以你不会从一开始就看到错误,因为你有同步 required
验证器。