Reputation: 20129
I created a custom filter to break an array of key-value pairs into an object that groups values by the first letter of a particular property. For example
Input:
[{foo: 'bar'}, {faz: 'baz'}, {boo: 'foo'}]
Output:
{f: [{foo: bar}, {faz: baz}], b: [{boo, foo}]}
However this filter seems to be causing an infinite digestion error in Angular.
var app = angular.module('app', []);
app.controller('ctrl', ['$scope', function($scope){
$scope.arr = [{name: 'foo', def: 'bar'}, {name: 'faz', def: 'baz'}, {name: 'boo', def: 'foo'}]
}]);
app.filter('firstLetterChunks', function() {
return function(input){
var chunks={};
for(var i = 0; i < input.length; i++){
var firstLetter = input[i].name[0].toUpperCase();
if(!(chunks.hasOwnProperty(firstLetter))) {
chunks[firstLetter]=[];
}
chunks[firstLetter].push(input[i]);
}
return chunks;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ctrl">
This caused a infdig error. Check your console.
<div ng-repeat="(firstletter, values) in arr | firstLetterChunks">
{{firstletter}}
<hr>
<div ng-repeat="value in values">
{{value}}
</div>
</div>
</div>
</div>
and I cant figure out why. From what I've found, this is usually caused by modifying your model in the filter, thus re-triggering the ng-repeat, however I don't think I'm doing this.
Upvotes: 0
Views: 83
Reputation: 17064
This happens because every filter call basically returns a new object, which has a new identity and therefore Angular believes something has changed. This in turn triggers a new digest cycle and this goes on until the 10 digests limit is reached.
I suppose there can be other ways to fix it with the use of caching to store your computed object and keep the filter, but I changed your code to the following which works just the same, but you have to recalculate chunks
if the array changes:
var app = angular.module('app', []);
app.controller('ctrl', ['$scope', function($scope){
$scope.arr = [{name: 'foo', def: 'bar'}, {name: 'faz', def: 'baz'}, {name: 'boo', def: 'foo'}];
function getChunks() {
var input = $scope.arr;
var chunks = {};
for(var i = 0; i < input.length; i++){
var firstLetter = input[i].name[0].toUpperCase();
if(!(chunks.hasOwnProperty(firstLetter))) {
chunks[firstLetter]=[];
}
chunks[firstLetter].push(input[i]);
}
return chunks;
}
$scope.chunks = getChunks();
}]);
And change the HTML call to:
<div ng-repeat="(firstletter, values) in chunks">
Upvotes: 0