简体   繁体   中英

Angular2 return data from validation service after Http call

I have build a validation service for my registration form and one of the static methods is checking if the entered email is available by calling my API the following:

static emailAvailable(control){

    let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]);
    let http = injector.get(Http);
    let valid = "E-mail is available";

    http.post('https://secretapi.com/email', JSON.stringify({ email: control.value }))
    .map((res: Response) => res.json())
    .subscribe(function(result){ 
        if(result.success){
            valid = result.success; //The console.log on the line below is correct, the one at the bottom of the script never changes.
            console.log(valid);
            return null; //Doesn't do anything?
        }else{
            valid = result.error; //The console.log on the line below is correct, the one at the bottom of the script never changes.
            console.log(valid);
            return { 'invalidEmailAddress': true }; //Doesn't do anything, just like the return above
        }
    });

    console.log(valid); //Output always "E-mail is available"
}

It should return "null" to the form validator when the email is available. The last console.log at the bottom should output the message that it recieves in the subscribe call. This doesn't happen and I'm not sure why. For some reason everything that happens within the subscribe call is contained there and never reaches the validator. What should I change? I have no idea and been searching the web for hours now.

You have to return Observable or Promise from your validator:

return http.post('https://secretapi.com/email', ...

console.log(...) doesn't make any sense here, since it will be executed after the Observable has been created as an object, but not after the ajax call has bee made.

If you want to output something after a response has been received, you have to move it inside subscribe

So in the end this website had the right answer. Also important to notice with the Angular2 Form validator to put the Async validators in the third (3) parameter and not together in an array in the second (2) parameter. That took me about 3 hours to figure out.

function checkEmail(control: Control){

let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]);
let http = injector.get(Http);

return new Observable((obs: any) => {
    control
        .valueChanges
        .debounceTime(400)
        .flatMap(value => http.post('https://secretapi.com/email', JSON.stringify({ email: control.value })))
        .map((res: Response) => res.json())
        .subscribe(
            data => {
                if(data.success){
                    obs.next(null);
                    obs.complete();
                } else {
                    obs.next({ 'invalidEmailAddress': true });
                    obs.complete();
                }   
            }
        );
});

}

The validator should look something like this, with the first validators checking on required and if it's actually an email address and the last doing an async call to the server to see if it's not already in use:

this.registerForm = this.formBuilder.group({
        'email': ['', [Validators.required, ValidationService.emailValidator], ValidationService.emailAvailable],
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM