如何向自定义字段添加异步验证器? [英] How to add an async validator to a CUSTOM field?
本文介绍了如何向自定义字段添加异步验证器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
有谁知道如何在自定义字段的类上声明ASYNC验证方法?
现在我的validate()
方法中有一个同步验证器:
@Component({
selector: 'my-field',
template: `<p>Some markup</p>`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MyFieldComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => MyFieldComponent), multi: true }
]
})
export class MyFieldComponent implements ControlValueAccessor {
validate(c: FormControl) {
// return null or error
}
// Rest of the code omitted for brevity
// writeValue(), registerOnChange()...
}
但即使我使用与上面相同的语法将NG_ASYNC_VALIDATORS
添加到提供程序,它也不允许我声明类似validateAsync()
方法的东西。
除非两种类型的验证器都以validate()
方法为目标,并且我需要在此方法中执行同步和异步验证,并且返回一个大的可观察(可能包装多个错误键)?我对此不太确定。
旁注:我可以做的是直接在提供程序中声明异步验证器,要么使用useValue
内联,要么使用useClass
作为单独的类。但我希望将其作为组件类和useExisting
的方法。
推荐答案
我不完全了解您的要求,但我可以给您一些建议,或许会对您有所帮助。
让我们从实现ControlValueAccessor
和Validator
(同步)的自定义字段开始:
@Component({
selector: 'my-field',
template: `<p>Some markup</p>`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MyFieldComponent), multi: true },
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => MyFieldComponent), multi: true }
]
})
export class MyFieldComponent implements ControlValueAccessor, Validator {
onChange = (_: any) => { };
onTouched = () => { };
constructor(private _renderer: Renderer, private _elementRef: ElementRef) { }
writeValue(value: any): void {
const normalizedValue = value == null ? '' : value;
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue);
}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
validationResult: any;
validate(c: FormControl) {
this.validationResult = { 'sync': true };
return null;
}
}
将实现AsyncValidator
DECLARE指令之后:
@Directive({
selector: 'my-field[formControlName],my-field[ngModel]',
providers: [{
provide: NG_ASYNC_VALIDATORS,
useExisting: forwardRef(() => CustomAsyncValidator),
multi: true
}]
})
class CustomAsyncValidator implements AsyncValidator {
valueAccessor: MyFieldComponent;
constructor(@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
this.valueAccessor = valueAccessors.find(x => x.constructor === MyFieldComponent) as MyFieldComponent;
}
// the same as above. I would use it
// constructor(@Self() private valueAccessor: MyFieldComponent) {}
/**
* presents global validation result async + sync
*/
validate(control: AbstractControl): Observable<any> {
return Observable.fromPromise(fakeAsyncValidator(1000)(control)).map(asyncResult => {
return Object.assign({}, asyncResult, this.valueAccessor.validationResult);
});
}
}
function fakeAsyncValidator(timeout: number = 0) {
return (c: AbstractControl) => {
let resolve: (result: any) => void;
const promise = new Promise(res => { resolve = res; });
const res = { 'async': false };
setTimeout(() => resolve(res), timeout);
return promise;
};
}
在上面的指令中,我们使用与自定义字段相同的选择器(my-field
),提供NG_ASYNC_VALIDATORS
,并在构造函数中注入现有组件(您可以注意到两个选项)。
最后,我们在此指令中有validate
方法,它尝试执行与您想要的类似的操作。
这篇关于如何向自定义字段添加异步验证器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文