Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UI-Router - scope not destroyed on state change?

I'm a new user to AngularJS and ui-router, and I'm trying to turn my head around on how the scope is managed. I was expecting the scope of an active controller would be destroyed when it becomes inactive on state change, however, it doesn't appear to be the case.

I've modified the example from UI-Router's website to illustrate the situation (see plunker below). Every time when the state route1.list/route2.list is triggered, they will emit an event on $rootScope. On receiving the event, a debug statement will be printed to console.

By toggling between the two states a few times, it is observed that all the controllers initialized previously responded the the event. So it appears that the scopes created by them have never been destroyed. Is this behavior expected? If so, what should I do such that only active controllers will respond to an event?

Plunker

Debug message printed on Console: enter image description here

Code:

var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){

// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/route1")

here is the route1

$stateProvider
  .state('route1', {
      url: "/route1",
      templateUrl: "route1.html"
  })
    .state('route1.list', {
        url: "/list",
        templateUrl: "route1.list.html",
        controller: function($rootScope, $scope){
          $rootScope.$emit("eventCT1");
          $rootScope.$on("eventCT2", fn);
          function fn () {
            console.log("Controller 1 receives an event emitted by Controller 2");
          }
          $scope.items = ["A", "List", "Of", "Items"];
        }
    })

and here is route 2

  .state('route2', {
      url: "/route2",
      templateUrl: "route2.html"
  })
    .state('route2.list', {
        url: "/list",
        templateUrl: "route2.list.html",
        controller: function($rootScope, $scope){
          $rootScope.$emit("eventCT2");
          $rootScope.$on("eventCT1", fn);
          function fn () {
            console.log("Controller 2 receives an event emitted by Controller 1");
          }
          $scope.things = ["A", "Set", "Of", "Things"];
        }
    })
 ...
like image 413
CLDev Avatar asked Nov 28 '15 08:11

CLDev


1 Answers

If we want to do something with

1) $rootScope inside of the controller (which has very limited lifetime),

2) we must destroy that, when controller (its $scope in fact) is being destroyed

So, this is the way how to hook and unhook

// get remove function
var removeMe = $rootScope.$on("eventCT2", ...);

// call that function
$scope.$on("$destroy", removeMe)

But, in the case above, we should not even try to

1) create some controller action for one state...

2) and expect it will be called in another controller from different state

These will never live together

like image 146
Radim Köhler Avatar answered Oct 17 '22 18:10

Radim Köhler