如何在不使用$ scope的情况下过滤列表。$ watch()?

时间:2015-03-04 18:31:57

标签: angularjs

我正在尝试在我的Angular模板中过滤一些数组,但是收到错误10 $digest cycles have been been reached,因此Angular会中止。经过一些搜索,这是因为filterFilter每次都返回一个新数组,所以Angular认为数组正在改变。

<tbody ng-if="!model.isLoading">
                <tr ng-repeat="user in filter(model.Users.dataSet, {'cTemplateId':model.UI.selectedTemplate.id}) track by user.id">
                    <td>{{user.id}}</td>
                    <td>{{user.firstName}}</td>
                    <td>{{user.lastName}}</td>
                    <td>{{user.emailAddress}}</td>
                    <td></td>
                </tr>
                <tr sk-no-result="filter(model.Users.dataSet, {'cTemplateId':model.UI.selectedTemplate.id})" label="No users found"></tr>
            </tbody>

这迫使我在控制器上使用$ watch:

$scope.$watch('model.UI.selectedTemplate', function(newVal){
        $scope.model.Users.filtered = filterFilter($scope.model.Users.dataSet, {'cTemplateId': $scope.model.UI.selectedTemplate.id});
    });

但我不喜欢这样,因为还有其他时候必须更新列表(例如更改分页)并且我不想为这些事件中的每一个创建$ watch。 / p>

有没有办法在HTML模板中运行过滤,以便它一直在更新?

2 个答案:

答案 0 :(得分:0)

数组中的对象是否具有ID或其他唯一标识符?

如果是这样,我认为你可以通过添加&#34; track by user.id&#34;来解决这个问题。 (或任何你的唯一标识符)到你的HTML。

<tr ng-repeat="user in filterFilter(model.Users.dataSet, {'cTemplateId': model.UI.selectedTemplate.id}) track by user.id">

答案 1 :(得分:0)

过滤后您的user看起来如何? ng-repeat需要根据tracking函数保留数组元素。

默认情况下,它跟踪整个对象(通过它们的$$ hashkey属性),这意味着如果filterFilter(...)每次读取都会返回新对象(即使对象看起来相同),Angular将无法稳定其摘要周期。

防止这种情况的一种方法是确保对filterFilter的同一调用将返回相同的数组(相同的指针),并使用一些缓存机制。

但是有一个更简单的解决方案,即跟踪特定属性而不是数组中每个项目的整个对象。例如,如果每个user都有唯一的id(被跟踪的属性必须是唯一的),您只需使用:

<tr ng-repeat="user in filterFilter(...) track by user.id)">

在某些情况下,当数组被排序并且同一个用户总是在同一个地方时,你可以简单地按照它们在数组中的索引进行跟踪:

<tr ng-repeat="user in filterFilter(...) track by $index)">

在下一个digect循环中,angular将检查数组中给定项的跟踪属性是否已更改,这在大多数情况下也比跟踪整个对象更高效。