2014-05-09 66 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