如何向自定义字段添加异步验证器? [英] How to add an async validator to a CUSTOM field?

查看:0
本文介绍了如何向自定义字段添加异步验证器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道如何在自定义字段的类上声明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的方法。

推荐答案

我不完全了解您的要求,但我可以给您一些建议,或许会对您有所帮助。

让我们从实现ControlValueAccessorValidator(同步)的自定义字段开始:

@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;
  }
}

将实现AsyncValidatorDECLARE指令之后:

@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

这篇关于如何向自定义字段添加异步验证器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆