AngularJS - 如何强制更新范围(数组项的承诺) [英] AngularJS - how to force a scope to update (promise for array item)
问题描述
我在 Angular 中创建了一个如下所示的控制器(为简洁起见进行了编辑):
I've created a controller in Angular that looks like this (edited for brevity):
function AppCtrl($scope, $http, $location, $dataService) {
$scope.projects = $dataService.data.projects;
}
从我的 $dataService
服务正确加载 $scope.projects
承诺.
Which correctly loads the $scope.projects
promise from my $dataService
service.
app.service('$dataService', function($q, $http, $location, $rootScope) {
var dataService = this; //Provides access 'this' inside functions below
var projectsDeferred = $q.defer();
$http.get('/api').success(function(data, status, headers, config) {
projectsDeferred.resolve(data.projects);
}).error(function(err) {
projectsDeferred.reject(err);
});
this.data = {projects: projectsDeferred.promise};
//UPDATE FUNCTION
function updateObjectInArray(array, object, newData) {
for(i in array) {
if(array[i] == object) {
if(newData != undefined) {
array[i] = newData;
} else {
return array[i];
}
}
}
return undefined;
}
this.updateProject = function(project, updateData) {
$http.put('/api/projects/' + project._id, updateData)
.success(function(data, status, headers, config) {
updateObjectInArray(dataService.data.projects.$$v, project, data);
}).error(function(data, status, headers, config) {});
};
});
我创建了另一个看起来像这样的控制器,它根据当前 URL 从项目数组中选择一个项目:
I've created another controller that looks like this, that selects a single project from the array of projects based on the current URL:
function ProjectCtrl($scope, $route) {
//Getting the current project from the array of projects
$scope.project = $scope.projects.then(function(projects) {
for(i in projects) {
if(projects[i]._id == $route.current.params.projectId) {
return projects[i];
}
}
});
}
当我尝试运行我的 updateObjectInArray()
函数时(在我的 $http.put()
请求成功时),我的 $scope.projects
已正确更新(项目数组),但 AppCtrl
中的 ProjectCtrl
中的 $scope.project
是 not 更新.我可以在 updateObjectInArray()
函数中记录 array[i]
,它会准确记录我期望的内容,并且我可以记录 $scope.projects
在 AppCtrl
中,它会相应地更新,但是当我尝试在我的 ProjectCtrl
控制器中记录 $scope.project
时,它 isn't 相应地更新.
When I try to run my updateObjectInArray()
function (on the success of my $http.put()
request), my $scope.projects
in AppCtrl
is correctly updated (the array of projects) but my $scope.project
in ProjectCtrl
is not updated. I can log array[i]
inside the updateObjectInArray()
function and it will log exactly what I expect, and I can log $scope.projects
in AppCtrl
and it will update accordingly, but when I try to log $scope.project
in my ProjectCtrl
controller, it isn't updated accordingly.
我认为原因是我更新了 array 后不得不调用
对象,但是,我收到 $rootScope.$apply()
或 $rootScope.$digest()
updateObjectInArray()
中的 [i]$digest 已在进行中
的错误.
I thought the reason was because I had to call $rootScope.$apply()
or $rootScope.$digest()
after I updated the array[i]
object in updateObjectInArray()
, however, I get the error that $digest is already in progress
.
我需要做什么来确保数组中的 $scope.project
项目在我的 ProjectCtrl
中得到更新?我需要为它解决一个新的承诺吗?
What do I need to do to make sure my $scope.project
item in the array gets updated in my ProjectCtrl
? Do I need to resolve a new promise for it?
推荐答案
一旦 projects
被加载,你就会使用数组 projects[i] 中的一项
,我们理论上假设它是内存中的对象 0x1
.问题是当一个新项目被加载时(让我们假设 0x2
),并且你更新了数组,你正在改变驻留在数组位置的对象(0x1
>),但 $scope.project
仍然引用现在废弃的对象 0x1
.你不能只在数组中改变它,你必须修改它,所以你不需要重新绑定 $scope.project
变量.
As soon as the projects
are loaded, you're using one of the items from the array projects[i]
, let's theoretically assume it's the object 0x1
in memory. The problem is that when a new item is loaded (let's assume 0x2
), and you update the array, you're changing the object that resides in the array position (the 0x1
), but $scope.project
still references the now abandoned object 0x1
. You can't just change it in the array, you have to modify it, so you don't need to rebind the $scope.project
variable.
最好的解决方案是更改 array[i] = newData
到 angular.extend(array[i], newData)
.这样,您只需更改 array[i] 的所有属性,并且当您的 $scope.project
指向内存中的同一个对象时,它将被更新.
The best solution is to change array[i] = newData
to angular.extend(array[i], newData)
. This way, you gonna just change all properties of array[i], and as your $scope.project
points to the same object in memory it will be updated.
无论如何,我也相信你可能想要改变 if(array[i] == object) {
to if(array[i]._id === object._id) {
和你的相等比较(==
)到严格相等比较(<代码>===).此 if
更适合您的原因,因为新创建的对象与旧对象不同.
Anyway, I also believe you may want to change if(array[i] == object) {
to if(array[i]._id === object._id) {
and your equality comparisons (==
) to strictly equality comparisons (===
). This if
suits better your cause, as the new created object is not the same as the old one.
这篇关于AngularJS - 如何强制更新范围(数组项的承诺)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!