0

I have an email input and I want to create a validator to check, through an API, if the entered email it's already in the database.

So, I have:

A validator directive

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);
  }
}

A component

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]],
    });
  }
}

And a template

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

A've made other validator this way (without the async part) and works well. I think te problem it's related with the promise. I'm pretty sure the code inside observable.subscribe it's running fine. What am I missing?

I'm using angular v2.1

1 Answer 1

1

Pretty sure your problem is this line:

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

You're passing your async validator to the synchronous validators array, I think the way it should be is this:

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

It would probably be more obvious if you'd use the new FormGroup(...) syntax instead of FormBuilder.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.