异步验证器不使用Angular中的模板驱动表单

时间:2017-05-18 09:46:15

标签: angular angular2-forms angular-validation

我为模板驱动表单创建了一个异步验证器。

import {Directive, forwardRef} from "@angular/core";
import {NG_ASYNC_VALIDATORS, Validator, AbstractControl, AsyncValidator} from "@angular/forms";
import {Observable} from "rxjs";


@Directive({
  selector: '[asyncValidator][ngModel]',
  providers: [{
    provide: NG_ASYNC_VALIDATORS, useExisting: forwardRef(() => AsyncAgeValidator), multi: true

  }]
})

export class AsyncAgeValidator implements Validator{

  validate(c: AbstractControl): Observable<{[key : number] : any}>{
      return this.validateAgeObservable(c.value);
  }

  validateAgeObservable( age: number ) {
    return new Observable(observer => {

      if( age === 20 ) {
        observer.next(null);
      } else {
        observer.next({asyncInvalid: true});
        console.log('validate');
      }
    });
  }

  }


}

我在我的模板中使用它如下,但我没有得到我期望从模板中的验证器的错误消息。调用将转到验证器,但我猜它没有在组件中注册observable。

<md-input-container>
  <input mdInput type="number" name="age" [(ngModel)]="user.age" placeholder="Age" required asyncValidator>
</md-input-container>

2 个答案:

答案 0 :(得分:4)

您的observable永远不会完成,因此Angular不知道何时更改表单状态。所以请记住你的观察结果必须完成。

您可以通过多种方式实现这一目标:

1)手动在观察者上调用complete()方法:

validateAgeObservable( age: number ) {
  return new Observable(observer => {
    observer.next(age === 20 ? null : {asyncInvalid: true});
    observer.complete();
  });
}

<强> Plunker Example

2)调用first()方法:

validate(c: AbstractControl): Observable<{[key : number] : any}>{
    return this.validateAgeObservable(c.value).first();
}

validateAgeObservable( age: number ) {
  return new Observable(observer => {
    observer.next(age === 20 ? null : {asyncInvalid: true});
  });
}

<强> Plunker Example

答案 1 :(得分:0)

添加到yurzui的第二个答案:

这有效:

validate(c: AbstractControl): Observable<{[key : number] : any}>{
    return this.validateAgeObservable(c.value).first();
}

这样做:

validate(c: AbstractControl): Observable<{[key : number] : any}>{
    return this.validateAgeObservable(c.value).take(1);
}