Where to put and how to achieve complex Navigational Logic?


So, we have a Navigation Service which schedules the logic which page follows which and if a user needs to be logged in etc, quite complex. And now I want to use `navController.push(page), but from my understanding this can only be used from within app.ts, so should I put this in app.ts, or is there a better, more modular way?


public next(nextPageString) {
   switch (nextPageString) {
            case "browse":
                this.nav.push(BrowsePage, {}, animationParams);
            case "goal-define":
                this.nav.push(GoalDefinePage, {}, animationParams);

Needless to say that above cases are endless. And I also did not find another way than to check for strings in order to get routing sorted out. Any ideas here are welcome.


We are using ngrx now, which is honestly absolute bliss - highly recommended. Make sure to use in


"@ngrx/core": "1.0.0",
"@ngrx/store": "2.0.1",
"ionic-angular": "2.0.0-beta.11",
"@angular/common": "2.0.0-rc.4",



@nottinhill … I am also working on a small side project basically to get familiar with ionic 2 and ngrx/store and ngrx/effects.

All good so far and I do get the concepts especially of the ngrx libs.

But I do struggle on how and where to put the navigation (aka the navCtrl.push(…) statements).

Consider the very easy flow for a login use case

  • user enters on one page its credentials
  • an ngrx actions is dispatched and a corresponding reducer changes the state in the store
  • a side effect for this login_action performs the API call and once completed returns new actions (as LOGIN_FAILURE or LOGIN_SUCCESS) which changes the state again.

My question is … where to put the logic to navigate after login API call to navigate the user to either something like a dashboard or to an error display page etc. (in case of false credentials …)

I tried to inject the nav controller into the effects- although it smells bad - but without success.

Any ideas? How did you manage to integrate navigation into an ngrx/ionic 2 app?



Hi @me_ten,

it does smell a bit but arguably these are side effects. Does someone else have a better strategy? I’d be interested as well.

This is how you do it from within an @Effect:

import { App, AlertController } from 'ionic-angular';
import { Dashboard } from '../pages/dashboard/dashboard';


  private app: App,
  private alertCtrl: AlertController,
) {}

Import and inject the App and get the navigation controller from there.

@Effect() loginSuccess$ = this.actions$
  .map(action => action.payload)
  .do((payload) => {
     this.storage.set('access_token', payload.access_token);

The alert works as usual.

@Effect() loginFailure$ = this.actions$
  .map(action => action.payload)
  .do((payload) => {
     let alert = this.alertCtrl.create({
       title: 'Login failed',
       subTitle: payload.error_msg,
       buttons: ['OK']


Hi @m165437,

I’m using a similar strategy but I have a Nav actions, reducer and relative effects:

// nav.actions.ts
export const ActionTypes = {
  PUSH:  type('[Nav] Push')

export class PushAction implements Action {
  type = ActionTypes.PUSH;

  constructor(public payload: NavInfo) { }

export type Actions
  = PushAction;
// nav.reducer.ts
export interface NavInfo {
  page: string;
  params?: any;
  isRootPage?: boolean;
  toRootNav?: boolean;

export interface State extends NavInfo {

export const initialState: State = {
  page: null,
  params: null,
  isRootPage: false,
  toRootNav: false

export function reducer(state = initialState, action: nav.Actions): State {
  console.debug(TAG, 'reducer()', { state, action });

  switch (action.type) {
    case nav.ActionTypes.PUSH: {
      const navInfo = (<nav.PushAction>action).payload;
      return Object.assign({}, state, navInfo);

    default: {
      return state;
// nav.effects.ts
export class NavEffects {
  @Effect({ dispatch: false })
  logout$: Observable<Action> = this.actions$
    .do((navInfo: NavInfo) => {
      console.debug(TAG, nav.ActionTypes.PUSH, { navInfo });

      const pageClass = resolvePage(navInfo.page);
      if (!pageClass) {
        console.warn(TAG, 'Page not found', navInfo.page);

      const navCtrl = this.app.getActiveNav();
      if (navInfo.isRootPage) {
      } else {

    private actions$: Actions,
    private app: App
  ) {

In this way I have also the navigation state in my store.
But I have an issue using the time-traversal in ngrx/store-devtools (redux plugin) basically it’s not working because the side-effects are not triggered for some reason.

Could be nice if some ngrx/ionic experts will find some time to write a module for that, like router-store-module for angular-route :slight_smile:


Hi @devmao,
i’m trying to use your solution to store my routing actions on ngrx, but I get lost on resolvePage(navInfo.page), do you resolve the page from a string? Are you using the page class name?
I couldn’t find anywhere in Ionic Api Docs a method to retrieve a page component from string


I’ve just upgraded to Ionic v3 yesterday, but I’ve learned that if you use the @IonicPage() methodology you can refer to the page controls with their name, a string: perfect for storing in the redux store.
So I believe in the above code you do not need the resolvePage(), just make navCtrl.push(navInfo.page).


Thank you ztp, I already found it on v3. Also I can’t get time-traversal to work…


Anyone get time travel to work ?


What do you mean when you say you decided to use relative effects? Do you mean you push and pop pages instead of setting the root nav?