请考虑控制器的以下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"));
删除$ scope。$ apply包装器并在getRecords方法中只留下“$ scope.accounts = data”会破坏代码。检索数据但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 :(得分: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
答案 1 :(得分:1)
您需要使用$ apply函数的原因是使用Breeze返回数据的结果。 $ apply函数用于获取角度以在所有内部监视上运行摘要并相应地更新范围。当角度范围内发生所有更改时,不需要这样做,因为它会自动进行摘要。在你的代码中,因为你正在使用Breeze,所以更改发生在角度范围之外,因此你需要获得角度来手动运行摘要,这对于在angular(jQuery,其他框架)之外发生的任何事情都是如此。等...)。确实,Breeze使用promises来更新数据,但Angular在promise返回后不知道如何处理更改,因为它超出了范围。如果您使用带有promise的角度服务,则视图将自动更新。如果你的代码工作正常,那么以这种方式使用$ apply是正确的方法。
我唯一可能建议的是改变你调用apply的方式,以确保它只在另一个摘要当前没有进行时才会运行,因为这会导致摘要错误。我建议你这样称呼函数:
if(!$scope.$$phase){$scope.$apply(function () {
$scope.accounts = data;
});
或者另一种选择是围绕$ apply函数编写一个自定义包装器,如SafeApply