Бесконечный цикл дайджеста в фильтре AngularJS
Я написал этот пользовательский фильтр для 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;
};
}).
Это соответствующий HTML:
<tr class='destination' ng-repeat-start='pickupAccount in pickupAccounts | department : {"selectedDepartment": selectedDepartment, "option": displayExclusive }'>
<!-- td here -->
</tr>
displayExclusive является логическим.
3 ответа:
Я написал этот пользовательский фильтр для AngularJS, но когда он запускается, я получаю бесконечную ошибку цикла дайджеста.
Имейте в виду, что фильтр должен возвращать массив той же структуры объекта. Когда мы активируем фильтр, он запускает цикл дайджеста, который снова будет работать над нашим фильтром. Если что - то изменилось в списке вывода-запускает новый цикл дайджеста и так далее. после 10 попыток он бросит нам
Infinite Digest Loopисключение
Тестирование
Этот пустой фильтр будет работать (100%). На самом деле мы здесь ничего не делаем, а возвращаем тот же самый объект, который получает фильтр.
filter('department', function(filterFilter) { return function(items, args) { var output = items; return output; }; })Теперь основная идея такова: напишите некоторое условие, чтобы подтолкнуть к
outputобъектам из входного списка a. e.itemsна основе некоторогоifоператора, a. e.var output = []; if (args.selectedDepartment.Id !== undefined && args.option) { angular.forEach(items, function(item) { if(<SOME CONDITION>) { output.push(item); } }); }Таким образом, это тоже будет работать.
Наш случай:
У нас есть такая логика:
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++; }Здесь мы полностью модифицировали объект, который был сохранен в
output. Так что в следующем цикле дайджеста нашitemsснова изменится и снова.
Заключение
Основная цель
Вышеупомянутая логика, которую вы написали, связана с манипуляцией данными,а не с фильтром. Фильтрfilter- фильтровать список, а не изменять содержимое объекта списка.departmentвозвращает одинаковую длину элементов.Для достижения своей цели вы можете использовать карту lodash или карту underscorejs, например.
Это происходит, когда вы манипулируете возвращаемым массивом таким образом, что он не соответствует исходному массиву. См., например:
.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; } }Вы можете увидеть, как это происходит в следующем упрощенном jsfiddle: https://jsfiddle.net/u873kevp/1/
Если возвращаемый массив имеет ту же "структуру", что и входной массив, это вызовет эти ошибки.
Это должно работать в вашем случае, просто назначив исходный элемент возвращаемому элементу:
if (productMatches.length !== 0) { output[count] = items[i]; // do this output[count].products = productMatches; output[count].firstProduct = items[i].firstProduct; count++; }
output[count] = {};Выше строка является основной проблемой. Вы создаете новый экземпляр, и
ng-repeatобнаружит, что модель постоянно изменяется бесконечно. (в то время как вы думаете, что ничего не меняется с точки зрения пользовательского интерфейса)Чтобы избежать этой проблемы, в основном вам нужно убедиться, что каждый элемент в модели остается "тем же самым", т. е.
Это равенство должно сохраняться до тех пор, пока вы не измените модель, таким образом,firstCallOutput[0] == secondCallOutput[0] && firstCallOutput[1] == secondCallOutput[1] && firstCallOutput[2] == secondCallOutput[2] ...ng-repeatне будет "ошибочно" думать, что модель имеет все изменилось. Обратите внимание, что два новых экземпляра не равны, т. е.{} != {}