lacoder lacoder - 5 months ago 99
AngularJS Question

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 ?

Answer

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