9

It seems, by default, the controller of the previous state is reloaded when you press the back button in the browser to go to a previous state. (this is not true in case of parent-child states)

How can I prevent that from happening?

Since I am not going to change any data in my current state which can affect the previous state, I don't want the previous state to reload again.

Here is a small plunker: http://plnkr.co/edit/xkQcEywRZVFmavW6eRGq?p=preview

There are 2 states: home and about. If you go to about state and then press back button, you will see that the home state controller is called again.

.state('home', { url: '/home', templateUrl: 'partial-home.html', controller: function($scope) { console.log('i was called'); } }) 

I believe this is the expected behavior, but I want to prevent it because my previous state (home in this case) is doing some visualizations which take some time to be created again.

1 Answer 1

6

Let's start with a global controller like GlobalCtrl which is added to the <body> or <html> tag like ng-controller="GlobalCtrl.

Doing this will enable us to keep the scope of this GlobalCtrl throughout your single page Angular app (as you are using ui-router).

Now, inside your GlobalCtrl define something like this:

$rootScope.globalData = {preventExecution: false}; // This callback will be called everytime you change a page using ui-router state $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) { $scope.globalData.preventExecution = false; // Just check for your states here if (toState.name == "home" && fromState.name == "about") { $scope.globalData.preventExecution = true; } }); 

Now, in your state configuration, you can use this $scope.globalData.preventExecution;

.state('home', { url: '/home', templateUrl: 'partial-home.html', controller: function($scope) { if ($scope.globalData.preventExecution) { return; } console.log('i was called'); } }); 

Answer to the question: The scope that we refer in the GlobalCtrl and the scope that we use in the State controller, how are they related?

Well, it is a very good question but it's simple. Every time a new scope is created in Angular, it always inherits its parent scope (unless isolated). So when your home state controller instantiated, its scope created using parent state i.e. $rootScope here in this case and we are instantiating the globalData in the $rootScope which is an Object (an Object in Javascript can be used to it's any nested object. Read this). So now when we are setting the globalData.preventExecution true/false, the same data can be used in the $scope of your home state controller. This is how both scopes are related or using the same data.

Answer to the question: is there some flag or setting in the ui-router which can accomplish this in general

If you want to achieve the above behaviour code for multiple states then you can write something like this:

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) { $scope.globalData.preventExecution = false; if (toState.name == "home" && fromState && fromState.preventHomeReExecution) { $scope.globalData.preventExecution = true; } }); 

Now, your states can be written like this:

.state('about', { url: '/about', templateUrl: 'partial-about.html', preventHomeReExecution: true }) .state('foo', { url: '/foo', templateUrl: 'partial-foo.html', }) .state('bar', { url: '/bar', templateUrl: 'partial-bar.html' preventHomeReExecution: true }) 

Basically, we are using preventHomeReExecution: true as a flag you wanted.

Sign up to request clarification or add additional context in comments.

3 Comments

Deleted my answer since this one is more detailed.
It is working. I am not able to understand one thing though, the scope that we refer in the GlobalCtrl and the scope that we use in the State controller , how are they related? it seems like the same scope is injected to the state controller as well or is it because of the rootScope being inherited?
Also, this code is very particular and i would have to write something like this for many state interactions, is there some flag or setting in the ui-router which can accomplish this. for example , don't reload the controller on back press at all, whatever be the states.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.