0
votes

I might sound dumb but I'm a newbie in angular2. I'm working on a project on ionic2, I've written an auth-service that has a function IsEmailAvailable() for async validation on input tag.

I'm unable to fire http.post request. I've tried many tutorials. I know http in angular2 return Observable which has many advantages. I've tried converting the http.post to .toPromise and tried using .then too. Still no progress.

this.http.post(MyApp.BASE_URL+"/api/auth/email",body).map(res => res.json())
         .subscribe(
           res   => {console.warn("some thing")},
           err => { console.error("some bullshit")},
           () =>  {console.log('Authentication Complete')}
         );

EDIT 1

  public isEmailAvailable(control : Control) {

    return new Promise(resolve => {
      let body =  JSON.stringify({username: control.value});
      console.log(body);
      let headers = new Headers({ 'Content-Type': 'application/json' });
      this.http.post(MyApp.BASE_URL+"/api/auth/email",body).map(res => res.json())
      .subscribe(
        res   => {console.warn("some thing")},
        err => { console.error("some bullshit")},
        () =>  {console.log('Authentication Complete')}
      );
    }); 
  }

EDIT 2 Just to add more insight to this. I'm using this isEmailAvailable function in a provider and using it as an async validator like this in my signup.ts page :

 constructor(private navCtrl: NavController, formBuilder : FormBuilder, 
       public globalVars : GlobalVars, public userData: UserData, public
       authService : AuthService)
{ 

     this.nav = navCtrl;
     this.signUpForm =  formBuilder.group({
     email :  [
        '',Validators.compose([]),authService.isEmailAvailable],
     password: ['',Validators.compose([
           Validators.maxLength(100),   
           Validators.minLength(6),
           Validators.required,
           Validators.pattern(globalVars.getPasswordPattern().toString())])]
     });
}
3
Why do you think the request is not triggered? Are you sure this.http.post(...) is called at all? - Günter Zöchbauer
Let me edit and post the whole function body. Even the promise inside which this http.post is also has console.log - Adil Sarwar
Be more specific about what's wrong. (1) can you confirm that the method is called? (2) that the http request is made? (3) that the server script received an responded? - BeetleJuice
1) Yes I Can confirm the method is called 2) If you have failed to see the title of question it quite explains what's wrong - Adil Sarwar
I didn't fail to see it but it didn't make sense. If you call the code why shouldn't it be executed. - Günter Zöchbauer

3 Answers

0
votes

Just removing Promise.resolve(...) should do:

public isEmailAvailable(control : Control) {

  let body =  JSON.stringify({username: control.value});
  console.log(body);
  let headers = new Headers({ 'Content-Type': 'application/json' });
  return this.http.post(MyApp.BASE_URL+"/api/auth/email",body).map(res => res.json())

  .do(res   => {console.warn("some thing")})
  .catch(err => { console.error("some bullshit"); return Observable.of([err]);})
  .toPromise().then(() =>  {console.log('Authentication Complete')});

Ensure you have everything imported (do, catch, of, toPromise)

0
votes

No need to use promises. And you don't want to call .subscribe() within the function itself. It's the calling code that should subscribe on the Observable that the function returns. I would do:

public isEmailAVailable(control:Control): Observable<any>{
   let body = ...;
   let headers = ...;
   let options = new RequestOptions();
   options.headers = headers;

   //suppose your server returns TRUE if email is available
   return this.http.post('...', body, headers).map(res => res.json())
            //async validators should return NULL if field is valid
            //or an object with the failure reason
            .map(res => res?null: {'Email is unavailable':true});   
}

By the way your original code does not include the headers in the POST request. I've addressed that as well.

Addendum: If you have to return a promise, use this return instead:

return new Promise ((resolve) => {
    //assumes your server returns TRUE if email is available
    this.http.post(...).map(res => res.json()).subscribe(
        //validator expects NULL when input is valid
        res => res? resolve(null): resolve ({'Email unavailable':true})
    );
});

You can see it working in this plunker. When null is outputted, the input is considered valid. When an object is outputted, it's considered invalid.

0
votes

So, I FINALLY got it working in my service by manually injecting http provider inside this service. For some reason the usual way of setting the provider reference in the constructor was working as I was using

THIS DID NOT WORK

http : any;
constructor (httpService : Http)
{
  this.http = httpService;
}

this way, it wasn't working as

this.http.post in isEmailAvailable() function

UPDATED: THIS DID WORK

isEmailAvailable(control : Control) {

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

    return new Promise(resolve => {
       let body =  JSON.stringify({username:control.value});

       let header = new Headers();
       header.append("Content-Type" , "application/json");

         // HERE I'm using manually injected http 

       return http.post(MyApp.BASE_URL+"/api/auth/email",body,{ headers: header}).map(res => res.json())
           .subscribe(
                res   => {console.warn("some thing")},
                err => { console.error("some bullshit")},
                () =>  {console.log('Authentication Complete')}
            );

 });