Angularjs 查找数组中已更改的项

Angularjs 查找数组中已更改的项,angularjs,Angularjs,使用AngularJS,我正在从AJAX请求加载一个项目数组,当我再次保存它们时,我只想发送已经更改的项目,而不是整个项目。但我看不到一个简单的方法来获取已经更改的项目。在加载时,我尝试这样做: originalData = angular.copy(data); $scope.notifications = data; 因此,当我保存时,我可以执行以下操作: var changed = $scope.notifications.filter(function (item, idx) {

使用AngularJS,我正在从AJAX请求加载一个项目数组,当我再次保存它们时,我只想发送已经更改的项目,而不是整个项目。但我看不到一个简单的方法来获取已经更改的项目。在加载时,我尝试这样做:

originalData = angular.copy(data);
$scope.notifications = data;
因此,当我保存时,我可以执行以下操作:

var changed = $scope.notifications.filter(function (item, idx) {
    return !angular.equals(item, originalData[idx]);         // hopefully they stay 
                                                             // in the same order!?!
});

这似乎有效,但感觉不太强健。注意关于订单的注释。我目前没有对项目进行重新排序,但我希望最终允许排序,我担心这会完全破坏这一点,迫使我尝试通过
id
originalData
数组中查找项目(这是每个项目具有的唯一属性),但这将是
O(n^2)
。我是不是漏掉了什么明显的东西?我知道项目是否脏,并将类应用于绑定的DOM元素。我也知道你可以使用
$watch
,但我想我需要为每个项目的每个属性设置一个watch,并在每个项目上设置某种
isDirty
标志,这样我就可以在save中进行筛选。

我决定这样做,我认为这比原始解决方案更好,因为它会在每个项目中保留原始项目的副本。加载数据时,我会执行以下操作:

angular.forEach(data, function(item) {
    item.$original = angular.copy(item);
}
var changed = $scope.notifications.filter(function (item, idx) {
    return !item.$original || !angular.equals(item, item.$original);
});
这将创建项目的深度副本并将其存储在
$original
中。请注意,属性名称的
$
前缀很重要,因为当我要保存时,我会执行以下操作:

angular.forEach(data, function(item) {
    item.$original = angular.copy(item);
}
var changed = $scope.notifications.filter(function (item, idx) {
    return !item.$original || !angular.equals(item, item.$original);
});
angular.equals
将忽略以
$
开头的任何属性(请参阅):

在属性比较期间,将忽略函数类型的属性和名称以$开头的属性

因此,它将对
项。$original
进行深入比较,而不尝试比较
$original
属性本身。
的第一个子句处理新项目的情况(显然没有
$original
属性)


现在,如果我以后对数组重新排序也没关系,因为我没有保留整个数组的副本,而是将每个项目的副本与项目本身一起保留。

您可以使用$watchCollection,但这只会通知您更改。此外,您可能希望使用$hash而不是索引。我们也需要尽快做到这一点;我将制作一个plunker。@CorySilva:据我所知,
$watchCollection
只会在集合中添加、删除或移动项目时通知您。我正在寻找一个项目的(在集合中)属性是否已更改。是的,你是对的,它将是$watch(func…,true)。此外,我还错误地指出了$hash,它是$$hashKey。我的错。@CorySilva:On
$hashKey
,据我所知,在绑定到
ng repeat
之前,不会添加它,因此原始数据的副本中没有它。所以我不确定我能用上它。在阵列上使用
$watch
会在某些内容发生更改时通知您,但它不会告诉您更改了哪个项目(
newValue
是整个阵列)。这里可能会出现下划线的差异。但在我们的应用程序中,我们会在将更改提交到服务器之前在服务中进行此差异检查。如果您需要更实时的阵列更新,您可能需要了解他们是如何完成阵列更新的。