使用observable时在angular 2异步验证器中返回什么

Eli*_*eth 6 angular2-forms angular2-observables angular

如果是,我必须在customerNameValidator中返回什么

异步验证失败/成功我的'customerName'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");
        }
   });
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*dam 10

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

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

返回值为true的对象是应该如何返回observable.您可能会错过异步验证器的一些重要步骤,但由于我们没有提供您的所有代码,因此很难说.请尝试查看本文本文以获取更多信息.


Geo*_*ang 8

我在角度6.1.1上实现了一个带有AsyncValidatorFn的反应形式.并希望分享我的一些学习经验

我发现angular不会(自动)更新AsyncValidatorFn的表单控件,就像它对内部同步验证器一样.

所以,根据"AsyncValidatorFn"接口规范,你必须在你的实现中"手动"更新表单控件

(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
Run Code Online (Sandbox Code Playgroud)

然后,您将检查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()]));
Run Code Online (Sandbox Code Playgroud)

自定义异步验证器和辅助函数

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;
  }
Run Code Online (Sandbox Code Playgroud)

请注意,我将控件作为参数输入到"mapErr"函数中,并通过"c.setErrors(err);"设置控件.

"回归错误;" 语句根据"AsyncValidatorFn"接口规范返回"ValidationErrors".

"gabriel.filter()"使用提取的用户名查询后端; 并为"ok","duplicated"和"operation failed"分别返回0,-100,-1

  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());
  }
Run Code Online (Sandbox Code Playgroud)

控件检查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>
Run Code Online (Sandbox Code Playgroud)

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

在我的例子中,我还使用内置的Validators.pattern来定义最小长度3.(参见上面的用户名formControl定义)

只要我的输入长度小于3,自定义异步验证器就不会触发.