加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angular – 如何将异步验证器添加到CUSTOM字段?

发布时间:2020-12-17 17:28:11 所属栏目:安全 来源:网络整理
导读:有谁知道如何在自定义字段的类中声明ASYNC验证方法? 现在我在validate()方法中有一个同步验证器: @Component({ selector: 'my-field',template: `pSome markup/p`,providers: [ { provide: NG_VALUE_ACCESSOR,useExisting: forwardRef(() = MyFieldCompone
有谁知道如何在自定义字段的类中声明ASYNC验证方法?

现在我在validate()方法中有一个同步验证器:

@Component({
  selector: 'my-field',template: `<p>Some markup</p>`,providers: [
    { provide: NG_VALUE_ACCESSOR,useExisting: forwardRef(() => MyFieldComponent),multi: true },{ provide: NG_VALIDATORS,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()方法为目标,我需要在此方法中同时执行同步和异步验证,并返回一个大的observable(可能包含多个错误键)?我对此不太确定.

侧面注意:我可以开始工作的是直接在提供者中声明异步验证器,可以使用useValue内联,也可以使用useClass作为单独的类.但是我希望将它作为使用useExisting的组件类的方法.

解决方法

我不完全明白你的要求是什么,但我可以给你一些想法,也许会帮助你.

所以让我们从实现ControlValueAccessor和Validator(sync)的自定义字段开始:

@Component({
  selector: 'my-field',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并在构造函数中注入现有组件(您可以注意到两个选项).

最后我们在这个指令中有验证方法,试图做你想要的类似的事情.

Plunker Example

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读