7

I'm trying to create a custom asynchronous validator, that goes to the server and checks if an email is already registered.

Unfortunately, it seems that the get request is never fired, because nothing happens. I've tried multiple console.logs inside subscribe, but they didn't run.

I've checked if that request works outside of the validator, and it does, so that's not the problem.

import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { Response, Http } from '@angular/http';

 @Component({
     templateUrl: 'build/pages/welcome/signup/signup.html',
     providers: [AuthService, CustomValidators]
})
export class Signup {

     signupForm: FormGroup;

     constructor(private formBuilder: FormBuilder, private http: Http) {

         this.signupForm = formBuilder.group({
             'email': ['', Validators.required, this.checkEmail],
         }):
     }

     checkEmail(control: FormControl): Promise<any> {

          const promise = new Promise<any>(
             (resolve, reject) => {

                 this.http.get('/sharealead/main.php?action=checkEmail').subscribe(
                     (res: Response) => {
                         console.log('it never gets here');
                         console.log(res)
                         if (res.text() == 'already there') {
                             resolve({'emailTaken': true});
                         } else {
                             resolve(null);
                         }
                     },
                     (err) => {
                         console.log('it never gets here');
                         console.log(err);
                    }
                 )   
             }
         );
         return promise;
     }

}

1 Answer 1

9

It's because you reference the function and you lose the this context. You can use the bind method or a wrapping arrow function to fix that (link the function to the component instance):

this.signupForm = formBuilder.group({
         'email': ['', Validators.required, this.checkEmail.bind(this) ],
});

or

this.signupForm = formBuilder.group({
         'email': ['', Validators.required, (control:Control) => {
           return this.checkEmail(control);
         } ],
});

In your case, this doesn't contain an http property...

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

5 Comments

Indeed, silly mistake, looks like I need one more lesson about this keyword in JavaScript (I'll mark your answer as accepted in about 8 minutes, when stackoverflow lets me)
You're welcome! Yes, the use of the this keyword in JavaScript is a bit specific...
Can you please also guide how to make such validator trigger on field blur only. In my case, its sending http requests even while I am typing email in the text box. So, before I finish typing my email address, it already has sent several request to server
For others with a similar symptom but different problem: I did not realize that async validators are only fired after all sync validators return valid (in angular 2.0.x at least).
for me it fires only once and doesn't care about model changes. Can you make a Plunker?

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.