有谁知道如何在自定义字段的类别中声明 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()
方法为目标,我需要在此方法中执行同步和异步验证并且返回一个大的可观察 em>(可能包装多个错误键)?我对此不太确定。
SIDE注意:我可以开始工作的是直接在提供商中声明异步验证器,与useValue
内联,或者与useClass
分开。但是我希望将作为组件类的方法与useExisting
。
答案 0 :(得分:5)
我不完全明白你的要求是什么,但我可以给你一些可能对你有帮助的想法。
让我们从实现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
:
@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
方法尝试执行类似的操作。
<强> Plunker Example 强>