2017-02-21 75 views
3

当我有什么在customerNameValidator返回如果什么在角2异步验证器可以通过观测

异步验证失败/成功,我的“客户名称” FormControl是无效的回报?

this.customerForm = this.formBuilder.group({ 
customerName: 
[this.newCustomerName, [Validators.minLength(2), Validators.required],[this.customerNameValidator.bind(this)]] 
}); 


customerNameValidator(c: AbstractControl) 
{ 
    return this.service.customerExists(c.value,this.companyId).subscribe(response => 
    { 
     if(response == true) 
     { 
      alert("true"); 
     } 
     else 
     { 
      alert("false"); 
     } 
    }); 
} 
+0

一个observable发出与验证器返回的内容相同的内容:如果没有错误,则返回null,如果有错误,则返回带有错误键的对象。 –

回答

6

您不应该订阅,而应该映射observable以更改返回流的结果,而不是从中读取。

customerNameValidator(c: AbstractControl) 
{ 
    return this.service.customerExists(c.value,this.companyId).map(response => 
    { 
     if(response == true) 
     { 
      return { customerExists: true }; 
     } 
     else 
     { 
      return; 
     } 
    }); 
} 

返回一个值为true的对象是您应如何返回observable。尽管你可能会遗漏一些重要的异步验证器步骤,但由于我们没有给出所有代码,所以很难说。 Try checking out this articlethis article了解更多信息。

+1

谢谢你的工作! – Elisabeth

+0

只是想知道新的自定义验证器类将如何实现在FormBuilder中的异步验证?谢谢 –

+0

@HungBui与其他自定义验证器类相同的方式将被实现。你的验证器应该是一个传入表单控件的函数。 https://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html – Adam

3

我使用角度为4.1.2的AsyncValidatorFn实现了一个被动式窗体。并想分享一些我的学习

我发现角度不会(自动)更新AsyncValidatorFn的窗体控件,因为它为内部同步验证程序。

左右,具体根据“AsyncValidatorFn”接口规范,你有你的实现

(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>; 

,然后为“手动”更新您的表单控件,您将检查在html元素

控制状态

果然不出我所实现的是一个用户名存在,检查可能会很常用在用户注册过程中发现以下

是代码摘录:

形式控制

// Supports alphabets and numbers no special characters except underscore('_') and dash('-') min 3 and max 20 characters. 
    this.userName = new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[A-Za-z0-9_-]{3,20}$')]),Validators.composeAsync([this.checkUser()])); 

自定义异步验证器和辅助功能

checkUser(): AsyncValidatorFn{ 

    return (c: AbstractControl): Observable<ValidationErrors> => { 
     return c 
     .valueChanges 
     .debounceTime(400) 
     .mergeMap(value => this.gabriel.filter({'userName':value})) 
     .map(stat => this.mapErr(c, stat)); 
    } 

    } 

    private mapErr(c: AbstractControl, res: any): ValidationErrors{ 
    let err: ValidationErrors; 
    switch (res['state']){ 
     case 0: 
     err = null; 
     break; 
     case -100: 
     err = {'existed': true}; 
     break; 
     case -1: 
     default: 
     err = {'failed': true};      
    } 
    c.setErrors(err); 
    return err; 
    } 

注意,我输入的控制作为参数进入“mapErr”功能,并设置由“c中的控制.setErrors(ERR);”。

“return err;”语句根据“AsyncValidatorFn”接口规范返回“ValidationErrors”。

“gabriel.filter()”用提取的用户名查询后端;并返回0,-100,-1分别 “OK”, “复制” 和 “操作失败”

filter(json): Observable<{}>{ 
    let body = JSON.stringify(json); 
    let headers = new Headers({'Content-Type': 'application/json'}); 
    let options = new RequestOptions({ headers: headers }); 
    return this.http.post(Cons.filter, body, options).timeout(10000).map((res:Response) => res.json()); 
    } 

控制在HTML文件中检查

<form [formGroup]="sf" (ngSubmit)="signin()"> 
      <ion-item> 
      <ion-label>UserName</ion-label> 
      <ion-input type="text" formControlName="userName" [class.invalid]="userName.dirty&&userName.invalid&&userName.errors!=null" ></ion-input> 
      </ion-item> 
      <p *ngIf="userName.dirty && userName.hasError('existed')"> 
       Username already existed 
      </p> 
      <p *ngIf="userName.dirty && userName.hasError('failed')"> 
       can not check validity of Username 
      </p> 
      <ion-item> 

我还发现了在同步验证器在一个表单控件中得到满足之前,异步验证器不会被触发。

在我的情况

,我还使用了内置Validators.pattern定义的3的最小长度(参见上述用户名formControl定义)

自定义异步验证器从未只要我的输入长度是触发短于3。