2014-05-09 33 views
2

请考虑以下angularjs代码控制器:

(function (app) { 
    var controller = function ($scope, $state, datacontext) { 
     $scope.$parent.manageTitle = "Account Management"; 
     $scope.accounts = []; 

     var init = function() { 
      getRecords(); 
     }; 

     var getRecords = function() { 
      return datacontext.getAccounts().then(function (data) { 
       $scope.$apply(function() { 
        $scope.accounts = data; 
       }); 
      }); 
     }; 

     init(); 
    }; 

    app.controller("accountsCtrl", ["$scope", "$state", "datacontext", controller]); 
})(angular.module("app")); 

删除$范围$适用的包装,并在getRecords方法打破了代码,只留下“$ scope.accounts =数据”。数据被检索,但html中的ng-repeat指令不会自动更新。我试图甩掉整个$ apply/$ digest模型,但可以肯定的是,在这种情况下不应该要求$ apply。

我做错了什么?

谢谢。

< ------------------------------------------编辑 - -------------------------------------->

好的,谢谢你的回复。这是datacontext。它使用Breeze。我仍然无法弄清楚问题所在 - - 我只是不明白为什么在上面的代码中需要$ apply。

(function (app) { 
    var datacontext = function() { 
     'use strict'; 
     breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true); 
     breeze.config.initializeAdapterInstance("ajax", "angular", true); 
     breeze.NamingConvention.camelCase.setAsDefault(); 

     var service; 
     var manager = new breeze.EntityManager('api/ProximityApi'); 
     var entityQuery = breeze.EntityQuery; 

     var queryFailed = function (error) { 
     }; 

     var querySuccess = function (data) { 
      return data.results; 
     }; 

     var getAccounts = function() { 
      var orderBy = 'accountName'; 
      return entityQuery.from('Accounts') 
       .select('id, accountName') 
       .orderBy(orderBy) 
       .using(manager) 
       .execute() 
       .then(querySuccess, queryFailed); 
     }; 

     service = { 
      getAccounts: getAccounts 
     }; 

     return service; 
    }; 
    app.factory('datacontext', [datacontext]); 
})(angular.module('app')); 

再次感谢!

+0

这一切都取决于什么'getAccounts()'方法返回... – gkalpak

+0

是DataContext的服务,并执行该服务使用的承诺? –

+0

datacontext是一项服务,您可以在控制器初始化的数组表示法中看到它。 – ryeballar

回答

1

您需要使用$ apply函数的原因是使用Breeze返回数据的结果。 $ apply函数用于获取角度以在所有内部手表上运行摘要并相应地更新范围。当角度范围发生所有更改时,这是不需要的,因为它会自动进行这种摘要。在你的代码中,因为你使用的是Breeze,所以变化发生在角度范围之外,因此你需要获得角度来手动运行摘要,对于角度外的任何事情(jQuery,其他框架等...)。的确,Breeze使用承诺来更新数据,但是Angular在承诺返回后不知道如何处理更改,因为它超出了范围。如果您使用带有承诺的角度服务,则视图将自动更新。如果你的代码正常工作,那么这将是以这种方式使用$ apply的正确方法。

我可能会建议的唯一方法是改变你调用apply的方式,以确保它只会在另一个摘要当前不在进行时才会运行,因为这会导致摘要错误。我建议你调用该函数这样:

if(!$scope.$$phase){$scope.$apply(function() { 
    $scope.accounts = data; 
}); 

或者其他的办法是写周围的$自定义包装应用功能这样SafeApply

3

谢谢您的回答。杰瑞德 - 你说得对。默认情况下,Breeze不使用角度$ q承诺,而是使用第三方Q.js承诺。因此,我需要$ apply将VM同步到视图。然而,最近Breeze人创建了angular.breeze.js,它允许Breeze代码使用角度承诺,取而代之。通过在应用程序中包含angular.breeze模块,所有Breeze代码将使用原生角度承诺和$ http代替。

这解决了我的问题,我可以删除$ apply调用。

参见:http://www.breezejs.com/documentation/breeze-angular-service