如何在Angular 2中使用反应/模型驱动的表单执行异步验证

时间:2016-10-26 19:01:15

标签: forms asynchronous angular angularjs-directive

我有一个电子邮件输入,我想创建一个验证器,通过API检查输入的电子邮件是否已经在数据库中。

所以,我有:

验证者指令

import { Directive, forwardRef } from '@angular/core';
import { Http } from '@angular/http';
import { NG_ASYNC_VALIDATORS, FormControl } from '@angular/forms';

export function validateExistentEmailFactory(http: Http) {
  return (c: FormControl) => {
    return new Promise((resolve, reject) => {
      let observable: any = http.get('/api/check?email=' + c.value).map((response) => {
        return response.json().account_exists;
      });

      observable.subscribe(exist => {
        if (exist) {
          resolve({ existentEmail: true });
        } else {
          resolve(null);
        }
      });
   });
  };
}

@Directive({
  selector: '[validateExistentEmail][ngModel],[validateExistentEmail][formControl]',
  providers: [
    Http,
    { provide: NG_ASYNC_VALIDATORS, useExisting: forwardRef(() => ExistentEmailValidator), multi: true },
  ],
})
export class ExistentEmailValidator {
  private validator: Function;

  constructor(
    private http: Http
  ) {
    this.validator = validateExistentEmailFactory(http);
  }

  public validate(c: FormControl) {
    return this.validator(c);
  }
}

组件

import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ExistentEmailValidator } from '../../directives/existent-email-validator';

@Component({
  selector: 'user-account',
  template: require<string>('./user-account.component.html'),
})
export class UserAccountComponent {
  private registrationForm: FormGroup;
  private registrationFormBuilder: FormBuilder;
  private existentEmailValidator: ExistentEmailValidator;

  constructor(
    registrationFormBuilder: FormBuilder,
    existentEmailValidator: ExistentEmailValidator
  ) {
    this.registrationFormBuilder = registrationFormBuilder;
    this.existentEmailValidator = existentEmailValidator;

    this.initRegistrationForm();
  }

  private initRegistrationForm() {
    this.registrationForm = this.registrationFormBuilder.group({
      email: ['', [this.existentEmailValidator]],
    });
  }
}

和模板

<form novalidate [formGroup]="registrationForm">
  <input type="text" [formControl]="registrationForm.controls.email" name="registration_email" />
</form>

A've以这种方式制作了其他验证器(没有异步部分)并且效果很好。我认为问题与承诺有关。我很确定observable.subscribe里面的代码运行正常。 我错过了什么?

  

我正在使用angular v2.1

1 个答案:

答案 0 :(得分:1)

非常确定你的问题就在这一行:

...
email: ['', [this.existentEmailValidator]],
...

您正在将异步验证器传递给同步验证器数组,我认为它应该是这样的:

...
email: ['', [], [this.existentEmailValidator]],
...

如果您使用new FormGroup(...)语法而不是FormBuilder,则可能更为明显。