Search code examples
angularjsangular-filters

Why do I get an infinite digest error here?


I need to create groups of things that come as a flat array, so I can open and close grid rows using a CSS grid system.

Here's how my HTML looks:

<div ng-repeat="row in items | GroupsOf: 3" class="row">
    [show stuff]
</div>

And here's the filter I wrote to support this:

.filter('GroupsOf', function(){     
    //Takes an array of things and groups them into  
    // sub-arrays with numPerGroup things in each 
    return function(things, numPerGroup){

        var i, group = -1, groups = []          
        for(i = 0; i < things.length; i++){
            //if it's a new group:
            if(i % numPerGroup === 0){                  
                groups.push([])
                group++
            }
            groups[group].push(things[i])
        }
        return groups//
    }
})

Although things render as expected, I'm getting infinite digest error when this runs, and therefore not everything gets wired up properly. Why do I get that error, and how do I fix the filter to work w/o erring?

I'd really prefer to do this as a filter rather than grouping the data in the controller, but I'll go the later route if someone can explain to me why it's just not achievable as a filter.


Solution

  • If you wanted to use $filter in the controller( which is certainly more performant and fixes the infinite $digest loop issue) you can do :

    angular.module('myApp', [])
    .controller('myCtrl', function($scope, $filter) {
        $scope.items = [
        'one','two','three',
        'unos','dos','tres',
        'uno','due','tre'
        ]
        $scope.grouped = $filter('GroupsOf')($scope.items , 3)
        console.log($scope.grouped)
    })
    .filter('GroupsOf', function(){     
    //Takes an array of things and groups them into  
    // sub-arrays with numPerGroup things in each 
    return function(things ,numPerGroup){
        var i, group = -1, res = []          
        for(i = 0; i < things.length ; i++){
            //if it's a new group:
            if(i % numPerGroup === 0){                  
                res.push([])
                group++
            }
            res[group].push(things[i])
        }
        return res
    }
    })
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <div ng-app="myApp" ng-controller="myCtrl">
      
    <div ng-repeat="row in grouped" class="row">
        {{row}}
    </div>
    
    
    </div>

    looking at the infdig documentation it seems your problem is caused by

    .. binding to a function which generates a new array every time it is called.

    that should be the reason $digest never finds a clean state.