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.

1 Like

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",
1 Like


@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?


1 Like

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']
1 Like

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:

1 Like

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?