Skip Navigation history when user in ION-TAB

Hello, I am developing an app application where in a page I have multiple tabs.

User can navigate any tab. But when he clicks on “<”, i need to take user to previous screen but not to previous tab.

Can some explain how to acheive this?

write your own backhandling for this page?

hide ionic-navbar-back button and show your own “custom” back button with an own function, which makes

$window.history.back();

But I don’t have in each screen. I placed >ion-nav-back-button> in my index.html page.

So you are saying hide in tab page and create my own custom button?

I think i need to hide ion-nav-back-button in each tab page and write my own custom method to navigate to back page.

But still it doesn,t solve my problem if I call $windows.history.back();

Let’s I have to two pages:

  1. Page1
  2. Page 2 - conatins Tab1,Tab2,Tab3

Now, user navigated from page1 to page2.

On page2, he naviagted tab1->tab2->tab3.

Now On tab3, he selected back button. I should take him to page1.

But,$window.history.back() it will take to page2->tab2.

Is that correct? Am i missing some thing?

No, ionic does a special back handling for ionic special things like tabhandling, popuphandling.
$window.history.back() navigates back in real browser history.

You can add a watcher to $state.current.name -> check if that state name is your “tab view” and set a variable to the scope in your index.html (true if it is the correct state, else false).

Now nghide ionic backbutton and show your own.
e.g .$window.history.go(-3); would go three steps back.

hmm, I tried this, but as i said,
When I am at Page2->tab3 , $window.history.back() is taking me Page2->tab2 not Page1.

i can use $window.history.go but I should alway keep track of Previous page when I am in CurrentPage.

Okay, how can I get “PreviousPage” details in currentPage?

Here is what I am going to Do:

  1. Store PreviousPage in currentpage.
  2. When user click back button, if $state.current.name==ION_TAB then $window.go(PreviousPage);

But. I need to know, hot to get previous page details from current page. Any idea?

Oh how ugly… i think ionic should not touch $window.history stack with tabs …

@mhartington
Do you know tab-handling manipulates window.history?
I think there should be a handling for that, outside of the window history (if you have tabs on a page, you have tabs to navigate with the tabs not over the window.history)

@mrvamsidhar
okay then you have to store all relevant data in a service.
It only holds a variable with a location path
If you need to recognize a previous state -> store the $location.path() on this variable or the backsteps.

Do not forget to clear this variable if you get back.

hmm… Currently, I am trying not to modify each controller. I have atleast some 30 odd controllers for my app (*.js files). I dont want to modify these pages. I need to run unit tests for all these,

Can you please tell me this, I had a abstract route. called app.state('app', { url: "/app", abstract: true, templateUrl: "app/layout/menu.html", controller: 'menuctr' })
all my other pages are like app.home, app.section etc. If I add variable to my abstract page controller, can I access in all derived pages? If not, is there any way to get this behavior?

You can access the parent state scope yes.

But you can also add additional variables to a state:

url: "/specialHandling",
   templateUrl: "app/layout/menu.html",
   controller: 'menuctr',
   hasSpecialBackButton: true
})

And you could listen to the ui-router statechange events:

There you could listen on the statechangestart event -> In that event you get toState and fromState.
Check if state has this flag or the statename is === ‘ION_TAB’ -> set variable for special handling e.g. on the $rootScope.

Listen to the state change you want to handle.

1 Like

Thank You. Let me try this.

  1. I will adding this $stateChangeSuccess in my abstract class.
  2. I will store “from” as PreviousPage in my abstract controller.
  3. on click of back button, if $state.current == ION_TAB them i call $state.go(PreviousPage).

I beleive it should work.

but, I want to make sure $window.history.back() actually takes back to tab page but not to previous page. Reason, I dont want to add some code which is not necessary. Hope you understand.

@mhartington/@calendee can you provide some input on this please?

@bengt​ler,
hmm I gave up for today. I think above solution might not be good. Here is my code.

   function menuctr($rootScope,$state){
 $rootScope.$on('$stateChangeSuccess', 
        function (event, toState, toParams, fromState, fromParams) {
    if (isTabItem(fromState.name) === false) {
                    vm.previousPage = fromState;
                    console.log('VM Previous Page-', vm.previousPage.name);
                }
}
     $scope.back = function () {
                
                if (isTabItem($state.current.name)) {
                    console.log('Current page is tab item - ', vm.previousPage.name);
                    debugger;
                    $state.go(vm.previousPage.name);
                
                }
                else {
                    $ionicNavBarDelegate.back();
                }
            }
    }

Above code perfectly works in happy path. But, when user navigated back to Page1 (after navigating Page2->tab1->tab2). and clicks on back button of page1. It is taking user to Page2->tab.
Which should not be.

hmm …looks like i hit wrong road. Let me know if you have any input on this.

Hello Any input on this please?

Hey there, sorry I’ve been on vacation for a week…

Hmm can you create a codepen of what you have so far? I’m kind of having a hard time following what you need tabs to do.

@mhartington, Here is my code.

Basically it has three Screens

1.Sign-In
2.Welcome
3.Schedule - This page has three Tabs. 

Please navigate to Schedule page. Then Click on each tab. Then select “<” on the top. Now,. Currently, It is navigating to previous tab. But,I want to navigate back to “Welcome” Page.

Please let me know how to achieve this.

Ah okay,

each tab is an own state. Now i got it^^.
Okay then it is not a tab-specific problem, because tabs are normaly handled like one state with content you want to split.
It is the correct behavior if you navigate from one to another state during tab-switching the states get pushed to the history stack and the back button works correctly if you get from tab3 to tab2 and so on ;).

For your problem i would analyse the routes.
If i only can navigate from a tab back to the welcome page and i only can get to the tabs over the welcome page i would do something like this

  1. Create little controller for each tab state
  2. if you get to default tab page -> the normal back-button functionality is correct
  3. if you get to tab 2 -> set a counter variable (e.g. backSteps) on the rootScope to 2, tab 3 = backSteps = 3
  4. if you are routing a “non-tabpage” -> set value to 0 or undefined
  5. you have only 1 back-action it checks if backSteps is there -> go back the steps else do only a history.back

If you are in touch with angular events ($emit, $broadcast, $on) you could trigger an event to set backsteps (to avoid using rootScope).

Sorry i have no time to build up an example.
Maybe @mhartington could help you more.

BTW: do not use href for navigate between states -> use ui-sref, ng-href or a ng-click to handle state navigation.

Hi @bengtler,

@bengtler,There is always chance that user will visit these tab pages from different other pages.(not only from welcome page he might from login page itself)

Anyway, its clear that i should use $Winddow.history.back() and $window.history.go(-n).

I implemented something like. I am currently doing some tests.

  1. Like you suggested, I added variable skipTabPagesto $rootScope to 0.
  2. On each tab page, while loading, I am decrementing skipTabPagesto -1. i,e,
    $rootScope.skipTabPages= $rootScope.skipTabPages-1;
  3. I override ion-nav-backbutton with my back() method. OnClick of back(),
    I am using $window.history.go( $rootScope.skipTabPages) only when $rootScope.skipTabPages<=0.

below is my code for your reference. Let me know if you find any error.

@mhartington, Kindly let me know your input on this.

    .controller('CustomersTabCtrl', function ($scope, $state,$rootScope) {

    $rootScope.currentView = 'CustomersTabCtrl';
    $rootScope.skipTabPages = $rootScope.skipTabPages - 1;
    console.log('**$rootScope.skipTabPages', $rootScope.skipTabPages);

})
.controller('OrdersTabCtrl', function ($scope, $state, $rootScope) {

    $rootScope.currentView = 'OrdersTabCtrl';
    $rootScope.skipTabPages = $rootScope.skipTabPages - 1;
    console.log('**$rootScope.skipTabPages', $rootScope.skipTabPages);

})
.controller('ProductsTabCtrl', function ($scope, $state, $rootScope) {
    $rootScope.currentView = 'ProductsTabCtrl';
    $rootScope.skipTabPages = $rootScope.skipTabPages - 1;
    console.log('**$rootScope.skipTabPages', $rootScope.skipTabPages);
   
})
.controller('MenuCtrl', function ($scope,$ionicNavBarDelegate,$window, $rootScope) {
    console.log('**Current View', $rootScope.currentView);
    $rootScope.skipTabPages = 0;
    $scope.back = function () {
        if ($rootScope.skipTabPages >= 0) {
            $window.history.back();
        } else {
            $window.history.go($rootScope.skipTabPages);
        }
        
        $rootScope.skipTabPages = 0;
    }
})

@bengtler, @mhartington,

please confirm my approach or if there is any better way. I need to implement this for my app which is scheduled to release soon. I had this issue pending for a while.

Thanks for your time and I sincerely appreciate your help.

Hey there, I’m looking into it right now :smile:

From the codepen provided and the plunkr, I couldn’t get things to work right. Do you mind integrating the two?

Sorry I didn’t understand.

I added my requirement at http://plnkr.co/edit/hMiP4dYth9GBobLjYn44?p=info2.

Do you want me to add my approach (above code) to plunker as well?

If you don’t mind. For some reason, it wasn’t working for me