18

我有一个表,用户可以选择根据某些列和这些列的某些值来过滤表中的行。跟踪此过滤器的对象结构如下所示:

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "OT", "NY"]
    },
    {
        "columnName": "weather",
        "values": ["humid", "sunny"]
    }
];

所以数组中的对象包含“columnName”和“values”键。“columnName”表示要为过滤器考虑的列,而“values”包含过滤器值。基本上,上面的数组将导致表中的行包含城市列包含“LA”、“OT”或“NY”作为值,而天气列包含“潮湿”或“晴天”作为值。不显示不包含这些值的其他行。

为了帮助更好地理解这个对象,如果用户希望只看到那些在“city”列中具有“LA”或“NY”的行,则结果数组将如下所示:

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "NY"]
    },
    {
        "columnName": "weather",
        "values": []
    }
];

用户设置或删除这些过滤器。每当发生这种情况时,都会更新上述数组。此更新正确发生并且我已经验证了它 - 这里没有问题。

问题在于 $watch()。我有以下代码:

$scope.$watch('activeFilterAttributes', function() {
    //Code that should update the rows displayed in the table based on the filter
}}

虽然$scope.activeFilterAttributes在用户更新 UI 中的过滤器时正确更新,但更新时不会触发 $watch。它在应用程序加载时第一次触发,但未来的更新对此没有影响。

我创建了一个小提琴来证明这一点:http: //jsfiddle.net/nCHQV/

In the fiddle, $scope.info represents the rows of the table, so to speak;
$scope.data represents the filter.
Clicking on the button is equivalent to updating the filter(in the case of the fiddle - the data) and thus updating the rows displayed in the table(in the case of the fiddle - the info). But as can be seen, the info is not updated on clicking the button.

Shouldn't $scope.$watch be triggered when the array of objects changes?

4

2 回答 2

66

The $watch method takes an optional third parameter called objectEquality that checks that the two objects are equal, rather than just share the same reference. This is not the default behavior because it is a more expensive operation than the reference check. Your watch isn't being triggered because it still refers to the same object.

See the docs for more info.

$scope.$watch('activeFilterAttributes', function() {
  // ...
}, true); // <-- objectEquality

Add that parameter and all is well.

于 2013-03-30T17:36:15.760 回答
5

Accepted answer is a bit out of date now as with AngularJS 1.1.4 the $WatchCollection function was added for use with arrays and other collections, which is far less expensive than a $Watch with the deep-equality flag set to true.

So this new function is now preferable in most situations.

See this article for more detailed differences between $watch functions

于 2015-07-06T13:45:25.500 回答