How to prevent a tab state change with $stateChangeStart ?!


I try to prevent a tab state change with a confirm dialog.
It doesn’t work, the state doesn’t change as expected BUT the view appears blank.
Any advice please?!
Note that this works for the link inside a tab but doesn’t work for a tab state change.
Please see the codepen and here is the code I have added in the controller (fork of the tabs and navigation demo)

			function (event, toState, toParams, fromState, fromParams) {

        console.log(' ';
        console.log(' ';
        if(confirm("Would you like to change state?")){
             console.log('go to: ';
	} else {
             console.log('stay at state: ';


Are you just trying to prevent the navigation or have something happen before the change?


@mhartington Hey, I am trying to have something happen before navigation.

Suppose I am on page ‘X’ and if user navigates to any other page, then I should Immediately stop the navigation and show a confirm box, if the dialog returns true then the page should navigate.

This is what I have done:

var foo = $scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
	   title: 'some title'
	}).then(function (res) {
	   if (res) {
	   } else {
$scope.$on('$destroy', foo)

But this does not work. How should I do it?


Actually I just try to prevent the navigation.
I wan’t to stay on the first tab if I do not confirm the change.
It works for basic links but not with a tab link.


So I’m still looking into this, but what I’m getting now is a nice little loop with the popup.

Still trying to work it out, but I figure I should post so we can all come to a solution for this.


Thanks for the help.
I’m not sure why, but when $stateChangeStart is raised, it’s already too late, the page is blank even if the state has not change yet. And preventing anything, at that time, doesn’t help.


@mhartington Yes exactly. Even I get the loop.



It is still not working with beta 8:
Does anybody have a solution for this?



Seems like it works for me only if I press confirm. So what needs to be fixed is the error statement.

else {
  console.log('stay at state: ';

I’ll do some digging around on why this isn’t working


The loop happens because on the resume selection, the $state.go triggers another $stateChangeStart which triggers another popup.


Try this solution :

It’s not great because you have to manually implement the tab state change, but it prevents the problems with using $stateChangeStart

P.S. You could also use the $ionicTabsDelegate to make this work using $


Thanks Calendee.
Unfortunately, this doesn’t solve my problem.

The reason I asked about $stateChangeStart is because I also want the confirm dialog to pop up when the user uses the hard back button (Android) to go back to a previous tab state.
This can be simulated on Firefox or Chrome with the “Del” key on keyboard.

I should have mentioned that sorry.

Story :
Click on “about tab”, confirm with “OK”.
Then hit the “del” key to go back to previous tab. No dialog appears.


I thought you might then want to use something like $urlRouter.sync() from$urlRouter

Unfortunately, this does not seem to work either. The transition occurs before the pop-up responds. I think has something to do with how the tabs delegate deals with changing tabs.

I’m out of ideas. Mike, you have any update?


Do you have any tips for this?


I think @Calendee solution is the best, but you could also include a custom back-button handler function.

  function () {
      title: 'some title'
    .then(function (res) {
      if (res) {
        console.log("You want to go back")

      } else {
        console.log("Cancelling navigation")

  }, 100


Hi, There.
I tried prevent the back button on the desktop browser or mobile browser.
so I made like this:

$rootScope.$on(’$stateChangeStart’, function (event, toState, toParams, fromState, fromParams) {

console.log(' ';
console.log(' ';

// prevent go back when press the back button on login page.
if ( === 'prepare' && === "login") {
// prevent go back when press the back button on home page.
if ( === 'login' && === "home") {


First time, this worked when I press the backbutton but,
it’s not working if I tried again,

any help?


I found a work-around that works for me. I believe the problem comes from the ionic tab bar. The tab bar already performs actions regarding the state change, while ui-router has not yet cleared the action for take-off.

In my scenario I wanted to event.preventDefault(), wait on a promise and considering the result of that promise either stay in the current state or continue with the state change (re-initiate). Staying in the current state does not work, since the tab bar has already decided to hide the current state/view. However, if you want to stay in the current state, you can just use $state.reload(), which will reload the current state and force the tab bar to show the original view/state again.


$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    event.preventDefault(); // Prevent state change, wait on promise

    .then(function() {
        $state.go(toState, toParams); // Continue with the initial state change
    .catch(function() {
        if($ === 'myState') {
            $state.reload(); // We were already in this state, sync tab bar


use ng-click instead of ui-sref. try if it works


@mhartington given that solution was to remove control from the tab by using ng-click, seems there is something odd going with ion-tabs directive not playing nice with ui-router.

Shouldn’t this be addressed? If so, I can create an issue on github and put some code example there.