AngularJS Group-By Filter
Filter to define when a field in an array of data changes from the previous value. Allows multiple filters and can be used in conjunction with OrderBy.
A future change will be to allow an array of fields to group by to be passed so that the multiple group-by filters don't have to re-iterate through the array for each one.
HTML
<div ng-app="myApp">
<div ng-controller='TestGroupingCtlr'>
<div ng-repeat="item in MyList | groupBy:'orderlineId'" >
<h2 ng-show="item.groupfield_CHANGED">{{item.orderlineId}}</h2>
<ul>
<li>{{item.name}}</li>
</ul>
</div>
<form role="form" ng-submit="AddItem()">
<input type="text" data-ng-model="item.groupfield" placeholder="Group">
<input type="text" data-ng-model="item.whatever" placeholder="Item">
<input class="btn" type="submit" value="Add Item">
</form>
</div>
</div>
JavaScript
var app=angular.module('myApp',[]);
app.controller('TestGroupingCtlr',function($scope) {
$scope.MyList = [
{name: 'test1', orderlineId: '52'},
{name: 'test2', orderlineId: '82'},
{name: 'test3', orderlineId: '82'}
];
$scope.AddItem = function() {
// add to our js object array
$scope.MyList.push({
groupfield:$scope.item.groupfield,
whatever:$scope.item.whatever
});
};
})
/*
* groupBy
*
* Define when a group break occurs in a list of items
*
* @param {array} the list of items
* @param {String} then name of the field in the item from the list to group by
* @returns {array} the list of items with an added field name named with "_new"
* appended to the group by field name
*
* @example <div ng-repeat="item in MyList | groupBy:'groupfield'" >
* <h2 ng-if="item.groupfield_CHANGED">{{item.groupfield}}</h2>
*
* Typically you'll want to include Angular's orderBy filter first
*/
app.filter('groupBy', function(){
return function(list, group_by) {
var filtered = [];
var prev_item = null;
var group_changed = false;
// this is a new field which is added to each item where we append "_CHANGED"
// to indicate a field change in the list
var new_field = group_by + '_CHANGED';
// loop through each item in the list
angular.forEach(list, function(item) {
group_changed = false;
// if not the first item
if (prev_item !== null) {
// check if the group by field changed
if (prev_item[group_by] !== item[group_by]) {
group_changed = true;
}
// otherwise we have the first item in the list which is new
} else {
group_changed = true;
}
// if the group changed, then add a new field to the item
// to indicate this
if (group_changed) {
item[new_field] = true;
} else {
item[new_field] = false;
}
filtered.push(item);
prev_item = item;
});
return filtered;
};
})