I have written this custom filter for AngularJS, but when it runs, I get the infinite digest loop error. Why does this occur and how can I correct this?
我已经为AngularJS编写了这个自定义过滤器,但是当它运行时,我得到了无限的摘要循环错误。为什么会发生这种情况,我该如何纠正?
angular.module("app", []).
filter('department', function(filterFilter) {
return function(items, args) {
var productMatches;
var output = [];
var count = 0;
if (args.selectedDepartment.Id !== undefined && args.option) {
for (let i = 0; i < items.length; i++) {
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
}
}
return output;
};
}).
This is the relevant HTML:
这是相关的HTML:
<tr class='destination' ng-repeat-start='pickupAccount in pickupAccounts | department : {"selectedDepartment": selectedDepartment, "option": displayExclusive }'>
<!-- td here -->
</tr>
displayExclusive
is boolean.
displayExclusive是布尔值。
3 个解决方案
#1
10
I have written this custom filter for AngularJS, but when it runs, I get the infinite digest loop error.
我已经为AngularJS编写了这个自定义过滤器,但是当它运行时,我得到了无限的摘要循环错误。
Keep in mind that filter should return array of the same object structure. When we activate filter, it fires digest cycle that will run over our filter again. If something changed in output list - fires new digest cycle and so on. after 10 attempts it will throw us Infinite Digest Loop
Exception
请记住,过滤器应该返回相同对象结构的数组。当我们激活过滤器时,它会触发将再次在我们的过滤器上运行的摘要循环。如果输出列表中的内容发生了变化 - 触发新的摘要周期等等。经过10次尝试后,它将抛出无限消化循环异常
Testing
This empty filter will works (100%). Actually we do nothing here but return the same object that filter receives.
这个空过滤器将起作用(100%)。实际上我们在这里什么都不做,但返回过滤器收到的同一个对象。
filter('department', function(filterFilter) {
return function(items, args) {
var output = items;
return output;
};
})
Now the main idea is: write some condition to push to output
objects from input list a.e. items
based on some if
statement, a.e.
现在主要的想法是:写一些条件来从输入列表a.e输出对象。基于if语句的项目,a.e。
var output = [];
if (args.selectedDepartment.Id !== undefined && args.option) {
angular.forEach(items, function(item) {
if(<SOME CONDITION>) {
output.push(item);
}
});
}
By this way it will work too.
通过这种方式它也会起作用。
our case:
we have this logic:
我们有这样的逻辑:
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
Here we completely modified object that has been stored in output
. So next digest cycle our items
will change again and again.
这里我们完全修改了存储在输出中的对象。所以下一个摘要周期我们的项目会一次又一次地改变。
Conclusion
The main purpose of filter
is to filter list and not modify list object content.
过滤器的主要目的是过滤列表而不是修改列表对象内容。
Above mentioned logic you wrote is related to data manipulation and not filter. The department
filter returns the same length of items.
您编写的上述逻辑与数据操作有关,而与过滤无关。部门过滤器返回相同长度的项目。
To achieve your goal, you can use lodash map or underscorejs map for example.
为了实现您的目标,您可以使用lodash map或underscorejs map。
#2
2
This happens when you manipulate the returned array in a way that it does not match the original array. See for example:
当您以与原始数组不匹配的方式操作返回的数组时,会发生这种情况。参见例如:
.filter("department", function() {
return function(items, args) {
var output = [];
for (var i = 0; i < items.length; i++) {
output[i] = {};
output[i] = items[i]; // if you don't do this, the next filter will fail
output[i].product = items[i];
}
return output;
}
}
You can see it happening in the following simplified jsfiddle: https://jsfiddle.net/u873kevp/1/
您可以在以下简化的jsfiddle中看到它:https://jsfiddle.net/u873kevp/1/
If the returned array does have the same 'structure' as the input array, it will cause these errors.
如果返回的数组与输入数组具有相同的“结构”,则会导致这些错误。
It should work in your case by just assigning the original item to the returned item:
只需将原始项目分配给返回的项目,它就可以适用于您的情况:
if (productMatches.length !== 0) {
output[count] = items[i]; // do this
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
#3
1
output[count] = {};
output [count] = {};
Above line is the main problem. You create a new instance, and ng-repeat
will detect that the model is constantly changed indefinitely. (while you think that nothing is changed from the UI perspective)
以上是主要问题。您创建一个新实例,ng-repeat将检测到模型是无限期地不断更改的。 (虽然您认为从UI角度来看没有任何改变)
To avoid the issue, basically you need to ensure that each element in the model remains the 'same', i.e.
为了避免这个问题,基本上你需要确保模型中的每个元素保持“相同”,即
firstCallOutput[0] == secondCallOutput[0]
&& firstCallOutput[1] == secondCallOutput[1]
&& firstCallOutput[2] == secondCallOutput[2]
...
This equality should be maintained as long as you don't change the model, thus ng-repeat
will not 'wrongly' think that the model has been changed.
只要您不更改模型,就应该保持这种相等性,因此ng-repeat不会“错误地”认为模型已被更改。
Please note that two new instances is not equal, i.e. {} != {}
请注意,两个新实例不相等,即{}!= {}
#1
10
I have written this custom filter for AngularJS, but when it runs, I get the infinite digest loop error.
我已经为AngularJS编写了这个自定义过滤器,但是当它运行时,我得到了无限的摘要循环错误。
Keep in mind that filter should return array of the same object structure. When we activate filter, it fires digest cycle that will run over our filter again. If something changed in output list - fires new digest cycle and so on. after 10 attempts it will throw us Infinite Digest Loop
Exception
请记住,过滤器应该返回相同对象结构的数组。当我们激活过滤器时,它会触发将再次在我们的过滤器上运行的摘要循环。如果输出列表中的内容发生了变化 - 触发新的摘要周期等等。经过10次尝试后,它将抛出无限消化循环异常
Testing
This empty filter will works (100%). Actually we do nothing here but return the same object that filter receives.
这个空过滤器将起作用(100%)。实际上我们在这里什么都不做,但返回过滤器收到的同一个对象。
filter('department', function(filterFilter) {
return function(items, args) {
var output = items;
return output;
};
})
Now the main idea is: write some condition to push to output
objects from input list a.e. items
based on some if
statement, a.e.
现在主要的想法是:写一些条件来从输入列表a.e输出对象。基于if语句的项目,a.e。
var output = [];
if (args.selectedDepartment.Id !== undefined && args.option) {
angular.forEach(items, function(item) {
if(<SOME CONDITION>) {
output.push(item);
}
});
}
By this way it will work too.
通过这种方式它也会起作用。
our case:
we have this logic:
我们有这样的逻辑:
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
Here we completely modified object that has been stored in output
. So next digest cycle our items
will change again and again.
这里我们完全修改了存储在输出中的对象。所以下一个摘要周期我们的项目会一次又一次地改变。
Conclusion
The main purpose of filter
is to filter list and not modify list object content.
过滤器的主要目的是过滤列表而不是修改列表对象内容。
Above mentioned logic you wrote is related to data manipulation and not filter. The department
filter returns the same length of items.
您编写的上述逻辑与数据操作有关,而与过滤无关。部门过滤器返回相同长度的项目。
To achieve your goal, you can use lodash map or underscorejs map for example.
为了实现您的目标,您可以使用lodash map或underscorejs map。
#2
2
This happens when you manipulate the returned array in a way that it does not match the original array. See for example:
当您以与原始数组不匹配的方式操作返回的数组时,会发生这种情况。参见例如:
.filter("department", function() {
return function(items, args) {
var output = [];
for (var i = 0; i < items.length; i++) {
output[i] = {};
output[i] = items[i]; // if you don't do this, the next filter will fail
output[i].product = items[i];
}
return output;
}
}
You can see it happening in the following simplified jsfiddle: https://jsfiddle.net/u873kevp/1/
您可以在以下简化的jsfiddle中看到它:https://jsfiddle.net/u873kevp/1/
If the returned array does have the same 'structure' as the input array, it will cause these errors.
如果返回的数组与输入数组具有相同的“结构”,则会导致这些错误。
It should work in your case by just assigning the original item to the returned item:
只需将原始项目分配给返回的项目,它就可以适用于您的情况:
if (productMatches.length !== 0) {
output[count] = items[i]; // do this
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
#3
1
output[count] = {};
output [count] = {};
Above line is the main problem. You create a new instance, and ng-repeat
will detect that the model is constantly changed indefinitely. (while you think that nothing is changed from the UI perspective)
以上是主要问题。您创建一个新实例,ng-repeat将检测到模型是无限期地不断更改的。 (虽然您认为从UI角度来看没有任何改变)
To avoid the issue, basically you need to ensure that each element in the model remains the 'same', i.e.
为了避免这个问题,基本上你需要确保模型中的每个元素保持“相同”,即
firstCallOutput[0] == secondCallOutput[0]
&& firstCallOutput[1] == secondCallOutput[1]
&& firstCallOutput[2] == secondCallOutput[2]
...
This equality should be maintained as long as you don't change the model, thus ng-repeat
will not 'wrongly' think that the model has been changed.
只要您不更改模型,就应该保持这种相等性,因此ng-repeat不会“错误地”认为模型已被更改。
Please note that two new instances is not equal, i.e. {} != {}
请注意,两个新实例不相等,即{}!= {}