7

I'am looking for the following possibility:

$stateProvider.state('user', angularAMD.route({
        url: '/user/:id',
        templateUrl: 'views/user.html',
        controllerUrl: 'views/user',
        controller: 'UserCtrl',
        onExit: function () {
            alert ("exit user");
           // call scope function saveCurrentStateData();

        }
    }));

saveCurrentStateData() stores some scope data (e.g. $scope.my.data) via a defined REST-Service at the backend.

EDIT: Can you give me a solution without $scope.$on ('destroy',.. maybe with resolve property of ui-router ? Why can't I use onExit, why it is here?

4 Answers4

8

You can listen to the $destroy $scope event of your controller

var UserCtrl = function ($scope) {
    $scope.$on('$destroy', function() {
        // Do your cleanup here or call a function that does
    });
};

And for a bit of reference of when does controller get instantiated and destroyed on ui-router, see this question

EDIT 1: If you want to access your $state parameters you can listen to the $stateChangeStart or $stateChangeSuccess events and do something like this

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState,fromParams) {
            if(fromState.name == 'yourstate'){
                // Here is your param
                console.log(fromParams.stateid);
            }
        });

EDIT 2: The reason that you cannot use onExit is because by the time that method is called the state has been already changed. However this is fixed in the next major version (1.0) by adding an injectable service called $transition$ which will provide access to the parameters of the state, you can read more about that here

Joel Hernandez
  • 1,817
  • 4
  • 18
  • 27
  • Please consider that `$state.params.stateid` is not working within `$scope.$on('destroy',..` --> I need that there.. –  Jan 26 '16 at 15:03
  • Then I believe you need to use the `$stateChangeSuccess` event, I do something similar in my applications but normally that state id represents something like a user, and that user lives within a service, meaning I know which user was on the page by accessing my service which does not get destroyed. There is no individual state events, just catch all. – Joel Hernandez Jan 26 '16 at 15:09
  • Updated answer with explanation of onExit @Vienna – Joel Hernandez Jan 26 '16 at 15:30
1

You can use the $destroy event of your controller, which is part of the controller lifecycle.

// In controller
$scope.$on('$destroy', function iVeBeenDismissed() {
  // say goodbye to your controller here
  $scope.saveCurrentStateData();
})

Read more for What is the lifecycle of an AngularJS Controller?

Community
  • 1
  • 1
Hristo Enev
  • 2,421
  • 18
  • 29
1

Hi you can use this event of ui-router

$scope.$on('$stateChangeStart', stateChangeStart(event, toState, toParams, fromState) {
// enter your code here;
});

or use this event

$scope.$on('$stateChangeSuccess', stateChangeSuccess(event, toState, toParams, fromState) {
// enter your code here;
});

Good Luck!

TERMIN
  • 824
  • 8
  • 18
  • I need something like "stateBeforeExit" –  Jan 26 '16 at 15:05
  • @Vienna in this case you may use a (angular) service you should update while you are in the required state, and inject it to the onExit function. – TERMIN Jan 27 '16 at 13:44
0

I'm not sure you are still interesting on the reason since there is an answer accepted. But I got a somehow related problem days ago and happened to see this question. I felt none of the previous answers got the exact point, so I'd to make mine. If my guess is correct, it is merely because the exit event did not happen at all (there is no full code in your question).

The exit of state happens if you navigate to ancestor states or sibling states, or sibling of an ancestor, but does not happen if you navigate to a descendant state. The document says:

When the application is in a particular state—when a state is "active"—all of its ancestor states are implicitly active as well.

I made a plnkr to illustrate; hope it can answer the question.

<!DOCTYPE html>
    <html ng-app="demo">
      <head>
        <meta charset="utf-8" />
        <title>Demo</title>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.6/angular.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.3/angular-ui-router.js"></script>
        <script>
          let app = angular.module('demo', ['ui.router']);
        
          app.config(['$urlRouterProvider', '$stateProvider', function ($up, $sp) {
            $sp.state(state1);
            $sp.state('state1.state2', state2);
            $sp.state('state1.state3',state3);
            $up.otherwise('/');
          }]);
          
          let state1 = {
            name: 'state1',
            url: '/',
            controller: function () {},
            template: `<p>I am state1</p>
            <div ui-view="state2view">
              <a ui-sref="state1.state2"> Jump to state1.state2</a>
            </div>
            <div ui-view="state3view">
              <a ui-sref="state1.state3"> Jump to state1.state3</a>
            </div>`,
            onExit: function(){alert('Goodbye state1')}
          };
          
          let state2 = {
            name: 'state1.state2',
            views: {
              state2view: {
                controller: function () {},
                template: 'I am state1.state2'
              }
            },
            onExit: function(){alert('Goodbye state1.state2')}
          };
          
          let state3 = {
            name: 'state1.state3',
            views: {
              state3view: {
                controller: function () {},
                template: 'I am state1.state3'
              }
            },
            onExit: function(){alert('Goodbye state1.state3')}
          };
    
        </script>
      </head>
    
      <body>
        <ui-view></ui-view>
      </body>
    </html>
zipper
  • 377
  • 1
  • 5
  • 18