I’m facing an issue that a lot of people have and debates on : I need to change the view when something happens in my service.
OK, broken design, I understood from many posts. But no solutions.
My problem :
I have API calls, and when one of them failed with 401, I need to redirect the user to login page. All my API calls are in a provider, and (of course), I don’t want to handle that case in every controllers.
I have also some angular2 components (@Component decorator) that are used in many places of the app, and they have link to other pages. But I can’t inject NavController in components (and components are part of the view isn’t it ?).
Some people said in old posts: “use events to send to controllers.” Ok. But how does it work ?
The only common piece of every call, is the “App” that bootstraps the application. How to send it an event through a @Component that is injected in deeper @Page, and in @Providers (and how to throw events in @Providers, that’s weird ?)
I (and I’ll probably not be the only one) will really appreciate a concrete example on how you can manage this kind of problems, 'cause I really don’t have a clean idea after many many days and tries.
One way to handle this is to have a service that contains an Observable<boolean> representing “are we authenticated?”. I use a ReplaySubject with a stack depth of 1. The app’s root page can inject NavController, subscribe to the authentication record service, and call nav.setRoot appropriately whenever a new state is entered. You can also employ similar logic in an attribute directive, if you want to go that way. When an API call gets a 401 error, you can call next(false) on the authentication recorder. When a login is successful, you call next(true) on it.
Which version of ionic are you using? almost a month ago the @Page was deprecated and now we use @Component decorator.
Also why not putting all http calls in a single service and in there override the actions when a 401 status code is received to go to login, for example i have a service that wraps all http calls, add then the access token as well as some info like dbUrl and user company, i only tell it to add the headers inside that service while i call it all over the app, you could do the same, just add this to be able to use the nav controller in injectables:
class httpService {
constructor(
public app: App
) { ... }
redirectToLogin() {
let nav = this.app.getActiveNav()
nav.setRoot(LoginPage);
}
}