# How to change page from service (@Injectable())

**URL:** <https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018>\
**Category:** ionic-v3\
**Created:** [March 31, 2016, 4:34pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018 "2016-03-31T16:34:24Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![royip](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@royip](https://forum.ionicframework.com/u/royip)\
**Post date:** [March 31, 2016, 4:34pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/1 "2016-03-31T16:34:24Z")

</div>

Hi

Is it possiable to change page from an injectable service?  
I tried `@ViewChild(Nav) nav` and nav is undefined  
I alos tried `this.nav = app.getComponent('nav')` by injecting `IonicApp` to the service but again nav and app are undefined

I looks like every effort to get the NavController to a service fails…  
I saw some issues about that but none of them helped me.

anyone?

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 5:02pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/2 "2016-03-31T17:02:09Z")

</div>

It is certainly possible to change page from an injected service but this may not be the best idea. **Services are generally used to work with data and shouldn’t change the DOM directly, and probably shouldn’t cause navigation either**. If however you have a good use case for this, it is possible.

```
import { Injectable } from 'angular2/core';
import { Router } from 'angular2/router';

@Injectable()
export class AuditDataService {
  constructor(private router: Router) {}

  goToTheHomeRoute() {
      this.router.navigate(['Home']);
  }
}

```

If the `goToTheHomeRoute` function is called the app will navigate to the home route. You must provide the route _name_, not path.

---

<div class="post-metadata">

**Author:** ![royip](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@royip](https://forum.ionicframework.com/u/royip)\
**Post date:** [March 31, 2016, 5:20pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/3 "2016-03-31T17:20:06Z")

</div>

this is the usecase:  
For every failed http request I tried to refresh the user’s access token with the refresh token he got in the login.  
If for some reason the refresh token fails i want to throw him back to the login screen…

It seams to me that its a bit of an overhead to wrap every http request in the pages with a navigation to the login screen  
You think this is a wrong case?

by the way? is there a way to give to a `@Page` a name?

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 5:45pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/4 "2016-03-31T17:45:44Z")

</div>

Seems like a good enough use case to me.

Regarding the page name piece that I have to say I am not sure of. My example was based on an Angular 2 router with route names set up rather than using Ionic 2’s navigation, so, sorry, I probably did not give you the best example. 😰

I should have looked at Ionic specifically rather than Angular, that’s my bad. I’ll try to get back to you with a better example if someone else doesn’t beat me to it.

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 7:08pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/5 "2016-03-31T19:08:53Z")

</div>

So, this is a really good question. From my understanding of the documentation, you cannot inject a NavController into a service. Ionic docs say:

> 

> ## Injecting NavController

> Injecting NavController will always get you an instance of the nearest NavController, regardless of whether it is a Tab or a Nav.

> Behind the scenes, when Ionic instantiates a new NavController, it creates an injector with NavController bound to that instance (usually either a Nav or Tab) and adds the injector to its own providers. For more information on providers and dependency injection, see Providers and DI.

Unfortunately it looks like all links within the docs are currently broken so I’m not sure what ‘Providers and DI’ would have lead to. But it seems Ionic gives you what it believes to be the proper instance of a `NavController` for you whenever you are in a `@Page`, so rather than instantiating a NavController like you normally would `providers: [NavController]`, Ionic handles this for you and you simply inject it in your constructor.

Which leaves the question…how would you do something like this? I’d be interested in hearing what @mhartington or @brandyshea or some other Ionic team member has to say about this.

---

<div class="post-metadata">

**Author:** ![xr0master](https://avatars.discourse-cdn.com/v4/letter/x/b4bc9f/32.png) [@xr0master](https://forum.ionicframework.com/u/xr0master)\
**Post date:** [March 31, 2016, 7:13pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/6 "2016-03-31T19:13:04Z")

</div>

> [@rlouie](#):
>
> you cannot inject a NavController into a service

But you can pass this service like argument. However, it is bad practice, as you said about it above.

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 7:14pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/7 "2016-03-31T19:14:07Z")

</div>

Ya, I mean, I can think of a couple hacky ways it might be possible but they all seem scary. Hopefully someone from Ionic can give us an idea.

---

<div class="post-metadata">

**Author:** ![xr0master](https://avatars.discourse-cdn.com/v4/letter/x/b4bc9f/32.png) [@xr0master](https://forum.ionicframework.com/u/xr0master)\
**Post date:** [March 31, 2016, 7:19pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/8 "2016-03-31T19:19:58Z")

</div>

? pass service like argument it is best way.

```auto
@Injectable()
export class AuditDataService {
  constructor(private router: Router) {}

  public checkToken(nav: NavController): void {
      if (!token.isValid) {
        nav.rootPage = LoginPage;
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![rapropos](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rapropos/32/100227_2.png) [@rapropos](https://forum.ionicframework.com/u/rapropos)\
**Post date:** [March 31, 2016, 7:46pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/9 "2016-03-31T19:46:43Z")

</div>

FWIW, here’s how I handled this situation. I have a dispatch page with a blank template, and a service that tracks the state of user authentication. Excerpted bits:

```auto
export class AuthTracker {
  loginNotifier: Subject<boolean>;
}

@Page({
  template: ``
})
@Injectable()
export class DispatchPage {
  constructor(nav: NavController, authTracker: AuthTracker) {
     let logsub = (loggedin) => {
      if (loggedin) {
        nav.setRoot(TabsPage);
      } else {
        nav.setRoot(LoginPage);
      }
    };
    authTracker.loginNotifier.subscribe(logsub);
}

```

The `LoginPage` also injects the `AuthTracker` and after successful login, calls `next(true)` on its loginNotifier. Similarly the class that handles logging out calls `next(false)`. `TabsPage` is the root of the ordinary application, so it gets swapped in as the main root whenever the user is logged in, and `LoginPage` gets swapped in when the user logs out. `DispatchPage` is the root of the app.

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 8:05pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/10 "2016-03-31T20:05:11Z")

</div>

This really isn’t the same issue. This keeps navigation in the page. The question was how do you navigate from within a service. That way if you have a service that makes 10 different api calls, and that service is used on 10 different pages, regardless of what page you are in if one of those api calls returns a 401 you get redirected to a login screen. Unless I’m not understanding your code.

---

<div class="post-metadata">

**Author:** ![rapropos](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rapropos/32/100227_2.png) [@rapropos](https://forum.ionicframework.com/u/rapropos)\
**Post date:** [March 31, 2016, 8:09pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/11 "2016-03-31T20:09:36Z")

</div>

> [@rlouie](#):
>
> regardless of what page you are in if one of those api calls returns a 401 you get redirected to a login screen

There would have to be an error handler in the service that calls `next(false)` on the loginNotifier in the case of the 401. Wouldn’t that achieve what OP wants?

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 9:21pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/12 "2016-03-31T21:21:08Z")

</div>

Ah, so AuthTracker would also be used in the service as well. In which case I get what you mean, sorry I didn’t follow that part in the original code example but I get you now.

But here’s my other problem though, at this point you are more or less doing the same thing @xr0master suggested, albeit in a different way. This might work but, it still concerns me with this whole NavController thing. Because now regardless of where you are in the app you are using the NavController Ionic decided to instantiate in the DispatchPage which may or may not be the same NavController instantiated on the page you are on.

This is where it’s not clear to me if this is okay or not, and why I wanted to hear from someone at Ionic. Because Ionic is managing those NavControllers…so I don’t know

---

<div class="post-metadata">

**Author:** ![rapropos](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rapropos/32/100227_2.png) [@rapropos](https://forum.ionicframework.com/u/rapropos)\
**Post date:** [March 31, 2016, 10:02pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/13 "2016-03-31T22:02:17Z")

</div>

> [@rlouie](#):
>
> you are using the NavController Ionic decided to instantiate in the DispatchPage which may or may not be the same NavController instantiated on the page you are on.

Hmm. In my situation, I don’t think that’s a problem, because the DispatchPage is the root page of the application. It’s the main gatekeeper that decides whether we go to the app (user is logged in), or we go to the login page (user is not logged in). In reality, there’s a third possibility of “user is not registered, go to the signup page”, but that’s probably not important here.

Even if there is some other NavController that’s controlling navigation within the mechanics of the various pages of the authenticated zone of the app (and I don’t know whether or not that’s the case), I think I always want the one associated with the DispatchPage handling login/logout/register/unregister events.

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 10:09pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/14 "2016-03-31T22:09:21Z")

</div>

Ya I think you are right, the whole NavController thing just seems like magic…which is both good and bad. Like, is it possible for that page to ever be destroyed? Probably not since it’s the root page like you say. Again, I think you are correct, it just weirds me out that we have this magic dependency injection that can’t be injected into services and we then have to pass around that injected object. I don’t think anything like that exists in vanilla Angular 2, but idk.

---

<div class="post-metadata">

**Author:** ![rapropos](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rapropos/32/100227_2.png) [@rapropos](https://forum.ionicframework.com/u/rapropos)\
**Post date:** [March 31, 2016, 10:18pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/15 "2016-03-31T22:18:12Z")

</div>

My mental image of it is something like this. Imagine that we have my Dispatch/Login/Tabs structure, so Dispatch can set root to either Login or Tabs. Let’s say Tabs has three tabs A/B/C, and each of those has subtabs 1/2/3.

We navigate to A2 and then to B1. There are now three NavControllers: one handling the Dispatch-to-Tabs line, one going Tabs-A-A2, and another (active) going Tabs-B-B1.

Now we click on the A tab. In order to remember that when we were on A, we were on A2, we reactivate the A line NavController, that knows it was pointing at A2.

In summary, I think the reason multiple NavControllers need to exist is to remember navigation paths that are currently dormant due to changes made higher up in the food chain, and in the particular situation involved in this discussion, we always want the NavController involved with the choice of “do we enter the app or require login?” to be the one associated with the dispatch page.

Of course, somebody on the dev team will probably be along to point and laugh at me any moment now, but live and learn.

---

<div class="post-metadata">

**Author:** ![rlouie](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rlouie/32/134973_2.png) [@rlouie](https://forum.ionicframework.com/u/rlouie)\
**Post date:** [March 31, 2016, 10:20pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/16 "2016-03-31T22:20:33Z")

</div>

Or they may say you are correct. What you are saying does make sense, it would just be nice to have some clarification.

---

<div class="post-metadata">

**Author:** ![angular2\_darmie](https://avatars.discourse-cdn.com/v4/letter/a/bcef8e/32.png) [@angular2\_darmie](https://forum.ionicframework.com/u/angular2_darmie)\
**Post date:** [April 28, 2017, 3:02pm UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/17 "2017-04-28T15:02:53Z")

</div>

Use Rx/Js Events to solve this problem

Setup your Service to send and receive events

```auto
mport { Injectable } from '@angular/core';
import {ServerConfig} from "./ServerConfig";
import {Http, Response} from "@angular/http";
import {Observable, Subject} from "rxjs/Rx";
import {HttpOptions} from "./HttpOptions";
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { ToastController} from 'ionic-angular';
import {Landing} from '../pages/landing/landing'; //Your landing page

@Injectable()
export class CentralService {
  private baseUrl:string;

  public controller:any;

  private subject:Subject<any> = new Subject<any>();

  constructor(private http: Http, private toast:ToastController) { }
    build(suffix:string, controller:any):CentralService{

        let cetUrl = (new ServerConfig(false)).url + "/user/";
        this.controller = controller;
        this.baseUrl = cetUrl + suffix;

       return this;
     }
  mySimpleHttpRequest():Observable<any>{
         return this.http.get(this.baseUrl + "/all", {headers: (new HttpOptions()).headers})
                 .map((res:Response) => {

                    return res.json();
                })
               .catch((error) => this.error(error))
   }

  gotoRoot(){
    this.subject.next("gotoRoot");
  }

  onRoot():Observable<any>{
    return this.subject.asObservable();
  }

  public error(err:any):any{
    console.log(err)
    if(err.status == 401){
      
      this.toast.create({
          message: 'Session Expired. Please Log In',
          duration: 3000,
          position: 'top'
        }).present();
      
      this.gotoRoot(); //Trigger the event 

      return Observable.throw(err.json() || "Server Error");
    }
    return Observable.throw(err.json() || "Server Error");
  }
}

```

Then in your controller/component

```auto
  ionViewDidLoad() {
 
    /**
    * Listen to the event and fire the action whenever the event is received!
    */

      this.centralService.onRoot().subscribe(res =>{
        this.navCtrl.setRoot(Landing)
      })

  }

```

---

<div class="post-metadata">

**Author:** ![kpsharma](https://avatars.discourse-cdn.com/v4/letter/k/87869e/32.png) [@kpsharma](https://forum.ionicframework.com/u/kpsharma)\
**Post date:** [August 4, 2017, 6:58am UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/18 "2017-08-04T06:58:25Z")

</div>

Hi all did we got any final answer to do so…

---

<div class="post-metadata">

**Author:** ![rapropos](https://sea1.discourse-cdn.com/ionicframework/user_avatar/forum.ionicframework.com/rapropos/32/100227_2.png) [@rapropos](https://forum.ionicframework.com/u/rapropos)\
**Post date:** [August 4, 2017, 7:38am UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/19 "2017-08-04T07:38:37Z")

</div>

> [@kpsharma](#):
>
> Hi all did we got any final answer to do so…

Not that you have to have any reason to care about my opinion, but it’s firmly that the topic of this thread is a horrible idea and should not be attempted.

---

<div class="post-metadata">

**Author:** ![kpsharma](https://avatars.discourse-cdn.com/v4/letter/k/87869e/32.png) [@kpsharma](https://forum.ionicframework.com/u/kpsharma)\
**Post date:** [August 4, 2017, 9:37am UTC](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018/20 "2017-08-04T09:37:52Z")

</div>

@rapropos i got you… now i just tring to handle my exception on a service layer method and then wanna paas it to another service layer … is it possible anyway ???

[Next page](https://forum.ionicframework.com/t/how-to-change-page-from-service-injectable/48018.md?page=2)
