6
votes

I create AuthHttpProvider which is Http wrapper which allow to send GET/POST/PUT/DELETE request and automagically add authentication token (jwt) to each request. And I use this wrapper instead Http in all my ionic2 app. Now i want to logout user (and go to loginPage) when I detect that any response from server has 403 Http error code.

So when I try to inject NavController (to use it to loginPage after 403 detection) in constructor by

constructor (public navCtrl: NavController)

I get:

Uncaught (in promise): Error: No provider for NavController

How to get access to navCtrl inside Provider?

2

2 Answers

16
votes

Here is solution (from this):

import { Injectable, Injector } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable } from "rxjs";
import 'rxjs/add/operator/map';
import { App } from "ionic-angular";
import { NavController } from "ionic-angular/index";
import { LoginPage } from "../../pages/login/login";
...

@Injectable()
export class AuthHttpProvider {

  private navCtrl: NavController;
  ...

  constructor(public http: Http, ..., private app:App ) {
    this.navCtrl = app.getActiveNav();
  }

  get(url) {  // http GET
    return this.http.get(url, this.getHeaders() )
                    .catch(this.globalErr(this));
  }

  // ... http POST/PUT/DELETE

  private getHeaders() { ... } //(cors, csrf-token ...)

  private globalErr(self) {
    return (err) => {
      if ( err.status == 403 ) { self.logout(); }
      return Observable.throw(err);
    };
  }

  public logout() {
    // ...
    this.navCtrl.setRoot(LoginPage);
    this.navCtrl.popToRoot;
  }
}

But better one will be if Provider be able to raise some event/exception and UI will able to intercept it and change view to loginPage

1
votes

You can do it like this it is very easy.

In your auth provider define an event

logoutEvent = new EventEmitter();

then in emit this event on logout

this.logoutEvent.next(true)

Subscribe to this event in app.component.ts like this

this.auth.logoutEvent.subscribe(
   res => {
       this.nav.setRoot(LoginPage);
   }
)

Hope this be of any use to anyone. thanks