Search code examples
angularjsangularjs-directiveangular-filters

Perform Group By and Sum by property in angularjs


Ok so have a simple page that displays a collection of objects in using ng-repeat="(key, value) in data| groupBy: 'Id'"I would like to group the data by a known property and also perform aggregate sum on one of the fields. I've used the angular-filter.js library leveraging the groupBy filter to facilitate this. The issue now is that I would like to also perform the aggregate sum and also display only a single row for each group. so say I have an array of objects,

`[{Id:1,name:"harry",volume:500},
{Id:1,name:"harry",volume:200},
{Id:2,name:"Fred",volume:150},
{Id:2,name:"Fred",volume:500},
{Id:3,name:"Sally",volume:450},
{Id:3,name:"Sally",volume:100}
]`

As shown above, the volumes are different for unique id's. I'd like to return this below after grouping by id and aggregating volumes(sum).

`[{Id:1,name:"harry",volume:700},
{Id:1,name:"Fred",volume:650},
{Id:1,name:"Sally",volume:550}
]`

EDIT I'd like to toggle between 2 displays i.e (all rows) and (grouped rows) as the case may be. I've implemented this by using ng-show with a checkbox flag to determine which view to display.I'd like to do this without having to write extra mark up as i've done here MyPlunkr SAMPLE
This way is my preferred way but there is a requirement to do this without writing to much extra mark up. Perhaps a custom filter would suffice ?


Solution

  • You have the grouped objects on each iteration, so finding the sum is very easy:

    $scope.getVolumeSum = function(items) {
        return items
            .map(function(x) { return x.volume; })
            .reduce(function(a, b) { return a + b; });
    };
    

    and

    <div ng-repeat="(key, items) in data | groupBy: 'Id'">
      id: {{ key }}, name: {{ items[0].name }}, volume: {{ getVolumeSum(items) }}
    </div>
    

    JSFIDDLE SAMPLE