Perform Group By and Sum by property in angularjs

2019-07-07 19:48发布

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 ?

2条回答
姐就是有狂的资本
2楼-- · 2019-07-07 19:53

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

查看更多
在下西门庆
3楼-- · 2019-07-07 20:03

I have been able to work around this i.e group the data and aggregate it so that It displays on the same view without having to create a separate one. I Implemented a custom filter.

angular.module('myApp',[])
.controller('Ctrl',[function($scope){
$scope.originalist = []// data is an array of objects.
    $scope.groupdata = function(showlist){
            $scope.newlist = showlist ? $filter('myCustomFilter')($scope.originalist): $scope.originalist; 
     }

}])
.filter('myCustomFilter',function(){
     return function(input){
     //Group the input data and aggregate where necessary
      return data
}

});

Then in the html document:

<input type="checkbox" ng-model="showlist" ng-change="groupdata (showlist)" />

also in the view:

  <tr class="ng-cloak" ng-repeat="d in originalist>
  </tr>

So I call the filter when the check box value showlist is set to true. Perhaps there is a better way but this is what has worked for me.

查看更多
登录 后发表回答