来自服务的$ rootscope对象模型并非(始终)在每个控制器中可用

时间:2013-04-25 11:31:35

标签: angularjs angularjs-scope

在我的应用定义中,我有:

var myVtModule = angular.module('vtApp', ['myAppDev','mongoAPI']);
myVtModule.run(function($rootScope, $location, Shop){
    $rootScope.shopData = {};
    Shop.getShop(function(response){
        $rootScope.shopData = response;
    });
})

Shop是从服务器检索数据的服务,它可以工作。问题是在控制器中我并不总是有权访问shopData,有时是空的,有时候工作正常。

function SupportCtrl($rootScope, $scope) {
    console.log ($rootScope.shopData);
}

为什么在收到服务响应时没有更新?我无法将Shop.getShop放在控制器中,因为我随处都需要它......

3 个答案:

答案 0 :(得分:1)

我的建议是使用控制器继承和服务,以便您的子控制器始终可以访问商店。这是一个演示:

http://beta.plnkr.co/edit/DtjwLMi3jHCdzThEJDNn?p=preview

代码:

angular.module('myApp', ['myApp.services']);

function MainCtrl($scope, ShopService) {
   $scope.shop = ShopService.getShop();
}
function ChildCtrl($scope) {
}
angular.module('myApp.services', []).
    factory('ShopService', function ($rootScope) {
        var shop = {
          storename: 'your store'
        };

        var service = {
              getShop: function() {
                return shop;
              }
        }

        return service;
    });

设置子控制器关系的HTML:

<html ng-app="myApp" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>
  <link rel="stylesheet" href="style.css">
  <script>document.write("<base href=\"" + document.location + "\" />");</script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
   The store is {{shop.storename}}
  <div ng-controller="ChildCtrl">
      The store name is: {{shop.storename}}

  </div>
</body>
</html>

您会注意到shop可供孩子使用,因为父范围会检索它。我设置了服务,因此您可以将其设置为可测试/等。除了继承之外,你可以轻松地将ShopService注入每个控制器并让它们进行调用,但是如果你有很多控制器可能会变得单调乏味。

有关范围继承的更多信息:

can i inherit a parent controller's variables? http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller

答案 1 :(得分:0)

如果您需要控制器中的结果,则应跳过myVtModule.run并执行以下操作:

function SupportCtrl($scope, Shop) {
  Shop.getShop(function(response){
    console.log (response);
    //do something, put response in $scope or $scope.$rootScope etc...
  });
}

答案 2 :(得分:0)

您的ng-controller范围所有原型继承自rootScope(最终),因此它们都可以访问您在rootScope上定义的任何对象。由于从服务器检索数据是异步操作,因此您的控制器可以在返回服务器数据之前执行。

您可以在控制器中使用$watch来确定数据实际可用的时间。但是,如果您只是希望在数据可用时更新您的视图,则不必使用$ watch。当数据可用时,Angular应自动更新您的视图。如,

function SupportCtrl($rootScope, $scope) {
  $scope.shopData = $rootScope.shopData;
}

然后在你看来:

<div ng-controller="SupportCtrl">shopData = {{shopData}}</div>

Fiddle - 我使用$timeout模拟了服务器延迟。请注意,在小提琴中我还使用angular.copy()更新控制器具有的引用,而不是将$rootScope.shopData分配给新的/不同的数组:

app.run(function($rootScope, $timeout){
    $rootScope.shopData = [];
    $timeout(function() {
        angular.copy([{d1: 'data1', d2: 'data2'}], $rootScope.shopData);
    }, 2000);
});