跨控制器共享变量

时间:2015-05-08 08:25:55

标签: angularjs

我有服务方法,

 var selectedType = 0;
 .........
 .........
 return {
            updateType: function (type) {
                return selectedType = type;
            },

            getType: function () {
                return selectedType;
            }
        }

我想在2个控制器之间共享这个selectedType变量。所以从一个控制器调用updateType方法并打开一个新的弹出页面,我调用getType方法。

问题是,getType方法总是在弹出页面中返回0,但是从主页面分配的值是2(通过调用updateType方法)。

主页,

angular.module('Controller1Module', [])
.controller('myController1', ['$scope', 'myService',
 function ($scope, myService) {
  myService.updateType(1);
 $scope.$watch(myService.getType , function(newValue, oldValue){                
            $scope.selectedType = myService.getType();                
        });
}

弹出控制器,

angular.module('Controller2Module', [])
.controller('myController', ['$scope', 'myService',
 function ($scope, myService) {

   $scope.$watch(myService.getType , function(newValue, oldValue){                
            $scope.selectedType = myService.getType();                
        });
}

我的服务,

angular.module('serviceModule', [])
 .service('myService', ['$rootScope',
  function($rootScope){
     var selectedType = 0;

       return {
               updateType: function (type) {
                return selectedType = type;
            },

            getType: function () {
                return selectedType;
            }
    ]);

2 个答案:

答案 0 :(得分:1)

以下是使用$scope.$watch查看myService.getType()更改的示例。此特定实现使用watch,因为myService.getType()返回的值是一个字符串(这是一个值),而不是一个对象(返回一个引用) - 服务selectedType中的任何更改您的控制器中的范围不会自动注意到该属性,因为它们仅在调用getType()时收到了服务中的内容值。



(function() {
  angular.module('myApp', [])
    .controller('Controller1', ['$scope', 'myService', Controller1])
    .controller('Controller2', ['$scope', 'myService', Controller2])
    .service('myService', ['$log', myService]);

  function Controller1($scope, myService) {
    $scope.$watch(
      myService.getType,
      function(newValue, oldValue) {
        $scope.selectedType = myService.getType();
      }
    );
    $scope.updateType = myService.updateType;
  }

  function Controller2($scope, myService) {
    $scope.$watch(
      myService.getType, //watch the service get function for changes in return value, then update local scope
      function(newValue, oldValue) {
        $scope.selectedType = myService.getType();
      }
    );
  }

  function myService($log) {
    var _selectedType = 0;

    function _updateType(type) {
      $log.log("updateType: " + type);
      return _selectedType = type;
    }

    function _getType() {
      $log.log("getType: " + _selectedType);
      return _selectedType;
    }

    return {
      updateType: _updateType,
      getType: _getType
    }
  }
})();

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="Controller1">
    <div>
      <input ng-model="newType" />
      <button ng-click="updateType(newType)">Update type</button>
    </div>
    Selected type in Controller 1: {{selectedType}}
  </div>
  <div ng-controller="Controller2">
    Selected type in Controller 2: {{selectedType}}
  </div>
</div>
&#13;
&#13;
&#13;

或者,请考虑以下内容(我已经演示了多个模块共享,因为我注意到您的评论中可能存在此要求):

&#13;
&#13;
(function() {
  "use strict";
  
  // define a services module that can be listed as a dependency of other modules
  angular.module('myApp.services', [])
    .service('myService', ['$log', myService]);

  //here we show the module containing our controller depends on the module with the service
  angular.module('module1', ['myApp.services']) 
    .controller('Controller1', ['$scope', 'myService', Controller1]);

  angular.module('module2', ['myApp.services'])
    .controller('Controller2', ['$scope', 'myService', Controller2]);

  // this is the module being used by ng-app='myApp' to tie it all together
  // note that since the controller modules already specify their dependence on the services module,
  // we don't need to list it again here.
  angular.module('myApp', ['module1', 'module2']);

  function Controller1($scope, myService) {
    $scope.data = myService.getData(); // we pass the whole object, and scope binding expressions have a '.' in them: {{data.selectedType}}
    $scope.updateType = myService.updateType;
  }

  function Controller2($scope, myService) {
    $scope.data = myService.getData();
  }

  function myService($log) {
    var _data = {
      selectedType: 0
    };

    function _updateType(type) {
      $log.log("updateType: " + type);

      _data.selectedType = type;
    }

    function _getData() {
      $log.log("getData called:");
      $log.log(_data);

      return _data;
    }

    return {
      updateType: _updateType,
      getData: _getData
    }
  }
})();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="Controller1">
    <div>
      <input ng-model="newType" />
      <button ng-click="updateType(newType)">Update type</button>
    </div>
    Selected type in Controller 1: {{data.selectedType}}
  </div>
  <hr />
  <div ng-controller="Controller2">
    <div>
      <input ng-model="data.selectedType" /> &lt;- 2-way binding, no separate update function needed
    </div>
    Selected type in Controller 2: {{data.selectedType}}
  </div>
</div>
&#13;
&#13;
&#13;

在上面的例子中,我们从服务中返回一个对象。由于对象是通过引用传递的,因此任何持有对它的引用的控制器都可以看到对服务中其属性的更改。这使得双向绑定非常容易。

请记住,如果替换服务中的对象而不是仅仅更新其属性,那么您将打破控制器对其进行的引用(实际上,控制器将维护对旧对象的引用) ,但您的服务将包含一个新的)。在这种情况下,辅助函数(如angular.extend和/或angular.copy)可以很容易地使用来自REST API调用返回的对象属性的数据更新服务中的任何对象,而无需完全替换对象(从而避免破坏参考文献。)

答案 1 :(得分:0)

我建议您创建一个 DataRepo 服务,该服务包含整个页面所需的所有数据。然后,您可以通过注入此服务来访问所有控制器中的相同数据:

myApp.factory('DataRepo', function() { 

    var defaultState = {
        selectedType: 1
    };

    return {
        state: angular.copy(defaultState)
    };
});

Fiddle