Search code examples
angularjsangular-filters

Filtering and grouping with angularJS group count


Given the following data:

[
{"Id": 3, "Name":"Image1.jpg", "AssetType":0, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 7, "Name":"Document1.jpg", "AssetType":2, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 8, "Name":"Video1.jpg", "AssetType":1, "Grouping": {"GroupingId": 4, "Name":"Other"}},
{"Id": 6, "Name":"Image2.jpg", "AssetType":0, "Grouping": {"GroupingId": 1, "Name":"Facebook"}},
]

I wanted to list separate groups of assets types, so I used the following ng-repeat:

<div class="group" ng-repeat="asset in assets | filterBy : ['AssetType'] : 0  "
    <b>{{ asset.Grouping.Name}}</b><br />
    {{ asset.Name }}
</div>

This gets me the following:

Other
Image1.jpg
Facebook
Image2.jpg

Now, I wanted to group by the grouping name, to test if there was only one group for this asset type. If there was only one, I was not going to show the grouping name, so I added a group by to the ng-repeat statement:

<div class="group" ng-repeat="(key, value) in assets | filterBy : ['AssetType'] : 0  | groupBy : 'Grouping.Name' ">
    <b>{{ key }}</b> - {{ numGroups(key) }}<br />
    <div ng-repeat="asset in value ">
        {{ asset.Name }}
    </div>
</div>

But when I added a function to get the count of keys for this filtered group, I got something unexpected:

Other - 5
Image1.jpg
Facebook - 8
Image2.jpg

numGroups is defined like this:

 $scope.numGroups = function (key) {
    return Object.keys(key).length;
}

I was expecting the length of keys to be 2 (Other and Facebook) but instead it looks like it is iterating all the items of the array.

Is there any way to get the count of group keys after a filter has been applied?

There is a way!

Here's how the solution worked out:

$scope.numGroups = function (map) {
    var count = 0;
    angular.forEach(map, function () { count++; });
    return count;
}

and the Html

<div class="group" ng-repeat="(key, value) in images = (assets | filterBy : ['AssetType'] : 0  | groupBy: 'Grouping.Name')  ">
    <div class="groupName" ng-hide="numGroups(images) == 1"><b>{{ key }}</b></div>
    <div ng-repeat="asset in value">
        {{ asset.Name }} - Brand {{ asset.Brand.Name }}
    </div>
</div>

Solution

  • In your function 'numGroups' you are getting the length of the 'Grouping.Name' String, it could be fixed if you use this:

    <div class="group" ng-repeat="(key, value) in grouped = (assets | groupBy : 'Grouping.Name') ">
            <b>{{key}}</b> - {{numGroups(grouped)}} <br />
            <div ng-repeat="asset in value">
                {{ asset.Name}}
            </div>
        </div>
    

    And a tricky way of your noumGroups function:

                $scope.numGroups = function(map){
                                        var count = 0;
                                        angular.forEach(map, function(){
                                            count++;
                                        })
                                        return count;
                                    }