Angular2模板驱动的异步验证器

时间:2016-03-26 12:45:27

标签: validation asynchronous typescript angular

我在模板驱动形式中定义异步验证器时遇到问题。

目前我有这样的意见:

<input type="text" ngControl="email"  [(ngModel)]="model.applicant.contact.email" #email="ngForm" required asyncEmailValidator>

带有验证器选择器 asyncEmailValidator ,它指向此类:

import {provide} from "angular2/core";
import {Directive} from "angular2/core";
import {NG_VALIDATORS} from "angular2/common";
import {Validator} from "angular2/common";
import {Control} from "angular2/common";
import {AccountService} from "../services/account.service";

@Directive({
selector: '[asyncEmailValidator]',
providers: [provide(NG_VALIDATORS, {useExisting: EmailValidator, multi: true}), AccountService]
})

export class EmailValidator implements Validator {
//https://angular.io/docs/ts/latest/api/common/Validator-interface.html


constructor(private accountService:AccountService) {
}

validate(c:Control):{[key: string]: any} {
    let EMAIL_REGEXP = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;

    if (!EMAIL_REGEXP.test(c.value)) {
        return {validateEmail: {valid: false}};
    }

    return null;

    /*return new Promise(resolve =>
        this.accountService.getUserNames(c.value).subscribe(res => {
            if (res == true) {
                resolve(null);
            }
            else {
                resolve({validateEmailTaken: {valid: false}});
            }
        }));*/
}

}

电子邮件正则表达式部分正在按预期工作,如果正则表达式匹配,表单正在成功验证。但之后我想检查电子邮件是否尚未使用,因此我为我的accountService创建了承诺。但这根本不起作用,形式一直处于失败状态。

我读过关于模型驱动的表单并使用如下的FormBuilder:

constructor(builder: FormBuilder) {
this.email = new Control('',
  Validators.compose([Validators.required, CustomValidators.emailFormat]), CustomValidators.duplicated
);
}

Control()的第三个参数中定义了异步验证器但是这不是我的情况,因为我使用了不同的方法。

所以,我的问题是:是否可以使用模板驱动的表单创建异步验证器?

3 个答案:

答案 0 :(得分:15)

您可以尝试使用NG_ASYNC_VALIDATORS密钥而不是NG_VALIDATORS密钥注册异步验证器的提供程序(仅适用于同步验证程序):

@Directive({
  selector: '[asyncEmailValidator]',
  providers: [
    provide(NG_ASYNC_VALIDATORS, { // <------------
      useExisting: EmailValidator, multi: true
    }),
    AccountService
  ]
})
export class EmailValidator implements Validator {
  constructor(private accountService:AccountService) {
  }

  validate(c:Control) {
    return new Promise(resolve =>
      this.accountService.getUserNames(c.value).subscribe(res => {
        if (res == true) {
            resolve(null);
        }
        else {
            resolve({validateEmailTaken: {valid: false}});
        }
    }));
  }
}

在angular.io网站上查看此文档:

答案 1 :(得分:2)

值得注意的是从那时起语法已经改变了,现在我使用的是角度4,下面是重写:

import { Directive, forwardRef } from '@angular/core';
import { AbstractControl, Validator, NG_ASYNC_VALIDATORS } from '@angular/forms';
import { AccountService } from 'account.service';

@Directive({
    selector: '[asyncEmailValidator]',
    providers: [
        {
            provide: NG_ASYNC_VALIDATORS,
            useExisting: forwardRef(() => EmailValidatorDirective), multi: true
        },
    ]
})
export class EmailValidatorDirective implements Validator {
    constructor(private _accountService: AccountService) {
    }

    validate(c: AbstractControl) {
        return new Promise(resolve =>
            this._accountService.isEmailExists(c.value).subscribe(res => {
                if (res == true) {
                    resolve({ validateEmailTaken: { valid: false } });
                }
                else {
                    resolve(null);
                }
            }));
    }
}

答案 2 :(得分:0)

我能够使用用户服务正确调用验证自定义验证器。我遇到的一个问题是,我将自定义验证器保留在Validators.compose()中。退出compose函数后,一切正常。

u