控制器切换后,访问服务数据在匿名功能中更改

时间:2015-03-13 05:07:12

标签: javascript angularjs

我简化了我的实际代码,但问题是一样的。在“第一个控制器”中单击Start counter匿名函数后,开始更改myService中的数据。首先它工作正常。但切换到“第二个控制器”后,即使您导航回“第一个控制器”,Angular也会停止自动更新<span ng-bind="getData().data">的值。

但是,如果您来回切换控制器,您可以看到控制器负载上的跨度正在更新,因此数据正在发生变化,控制器可以访问它。只是Angular不再自动跟踪它了。

如何让Angular在再次切换控制器后开始跟踪更改并更新元素?

<html>
<head>
<script src="https://code.angularjs.org/1.4.0-beta.4/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-beta.4/angular-route.min.js"></script>
</head>
<body>

<div style="padding: 0 0 20px 0">
    <a href="#/first">First controller</a> | <a href="#/second">Second controller</a>
</div>

<div ng-app="myApp">
    <div ng-view></div>

    <script type="text/ng-template" id="temp1.html">
        Data: <span ng-bind="getData().data"></span>
        <br/>
        <button ng-click="start()">Start counter</button>
    </script>

    <script type="text/ng-template" id="temp2.html">
        Data: <span ng-bind="getData().data"></span>
    </script>
</div>  

<script type="text/javascript">
    var myControllers = angular.module('myControllers', []);

    myControllers.factory('myService', [function() {
        return { data: 0 };
    }]);

    myControllers.controller('myController1', ['$scope', 'myService', function($scope, myService){
        $scope.getData = function() {
            return myService;
        }

        $scope.start = function() {
            setInterval(function() {
                myService.data++;
                $scope.$apply();    
            }, 1000)
        }
    }]);

    myControllers.controller('myController2', ['$scope', 'myService', function($scope, myService){
        $scope.getData = function() {
            return myService;
        }
    }]);

    var myApp = angular.module('myApp', [
      'ngRoute',
      'myControllers'
    ]);

    myApp.config(['$routeProvider',function($routeProvider) {
        $routeProvider.
            when("/first",{ controller: "myController1", templateUrl: "temp1.html"}).
            when("/second", {controller: "myController2", templateUrl: "temp2.html"}).
            otherwise({redirectTo : "/first"});
    }]);

</script>

</body>
</html>

1 个答案:

答案 0 :(得分:0)

所以我实际上在这里找到了答案:Passing data between controllers using service and confusion with using [ '$scope' , 'service' , function($scope, service){}](见 Anthony Chu于2014年2月17日6:12 的评论)。诀窍是使用$rootController通过事件警告所有其他控制器以更新服务中的数据。因此,匿名函数将在后台运行,而不会引用新的$scope,但新$scope将通过$rootScope事件向下传播从其接收消息。

我已将$root.$broadcast(...)附加到匿名函数,并将相应的$scope.$on(...)附加到两个控制器。所以控制器代码现在看起来像这样:

myControllers.controller('myController1', ['$scope', 'myService', '$interval', '$rootScope', 
  function($scope, myService, $interval, $rootScope) {
    $scope.getData = function() {
      return myService;
    }

    $scope.$on('myupdate', function() {
      if (!$scope.$$phase) { //checks that Angular is not updating scope right now
        $scope.$apply();
      }        
    });

    $scope.start = function() {
      setInterval(function() {
        myService.data++;
        $rootScope.$broadcast('myupdate');
      }, 1000)
    }
}]);

myControllers.controller('myController2', ['$scope', 'myService',
  function($scope, myService) {
    $scope.getData = function() {
      return myService;
    }

    $scope.$on('myupdate', function() {
      if (!$scope.$$phase) {
        $scope.$apply();
      }        
    });
}]);

Fully working code example