Reputation: 385
import {
Pipe,
PipeTransform
} from '@angular/core';
/*
* Group an array by a property (key)
* Usage:
* value | groupBy : 'field'
*/
@Pipe({
name: 'groupBy'
})
export class GroupByPipe implements PipeTransform {
transform(value: Array < any > , field: string): Array < any > {
// prevents the application from breaking if the array of objects doesn't exist yet
if (!value) {
return null;
}
const groupedObj = value.reduce((previousVal, currentVal) => {
if (!previousVal[currentVal[field]]) {
previousVal[currentVal[field]] = [currentVal];
} else {
previousVal[currentVal[field]].push(currentVal);
}
return previousVal;
}, {});
// this will return an array of objects, each object containing a group of objects
return Object.keys(groupedObj).map(key => ({
key,
value: groupedObj[key]
}));
}
}
I have implemented a custom groupBy pipe but it only works for a simple object string for instance it works when i pass something like this:
console.log(new GroupByPipe().transform(this.selectedServices, 'name'));
But i want to pass something more complex like this:
console.log(new GroupByPipe().transform(this.selectedServices,'paymentCycle.name'));
How can I make this pipe to accept a more complex groupBy such as this:
console.log(new GroupByPipe().transform(this.selectedServices, 'paymentCycle.name'));
Upvotes: 2
Views: 5656
Reputation: 9124
I suggest to not implement the groupBy by yourself. Use lodash groupBy instead, it is capable of what you are searching for.
const data = [
{ foo: { name: "A", id: "1" } },
{ foo: { name: "B", id: "1" } },
{ foo: { name: "A", id: "2" }}
];
console.log(_.groupBy(data, 'foo.name')); // import * as _ from 'lodash';
(see https://lodash.com/docs/4.17.15#groupBy)
Results in
{A: Array(2), B: Array(1)}
A: Array(2)
0: {foo: {…}}
1: {foo: {…}}
length: 2
__proto__: Array(0)
B: Array(1)
0: {foo: {…}}
length: 1
__proto__: Array(0)
__proto__: Object
Upvotes: 1