I'm looking way to do something like
JS
$scope.players = [
{name: 'Gene', team: 'alpha'},
{name: 'George', team: 'beta'},
{name: 'Steve', team: 'gamma'},
{name: 'Paula', team: 'beta'},
{name: 'Scruath', team: 'gamma'}
];
HTML:
<ul repeat.for="obj of players | groupBy: 'team'">
Group name: ${obj.group}
<li repeat.for="player of obj.values">
player: ${player.name}
</li>
</ul>
Is it possible to do? Or what the better way to do this logic in Aurelia way?
You can do this using a ValueConverter
.
export class GroupByValueConverter {
toView(array, groupBy) {
var groups = {};
array.forEach(function (o) {
var group = o[groupBy];
groups[group] = groups[group] || [];
groups[group].push(o);
});
return Object.keys(groups).map(function (group) {
return {
group: group,
values: groups[group]
};
})
}
}
After finding this answer, I did it in a slightly different way. Instead of using a an array of objects with group
and value
keys, I used a Map
.
Updated view
<ul repeat.for="[group, values] of players | groupBy:'team'">
Group name: ${group}
<li repeat.for="player of values">
player: ${player.name}
</li>
</ul>
For the value converter I used this answer for inspiration on an efficient way to perform a group by operation.
Value Converter
export class GroupByValueConverter {
toView(objects, key) {
return objects.reduce(
(rv, x) => rv.set(x[key], (rv.get(x[key]) || []).concat(x)),
new Map()
);
}
}
An extension to the ValueConverter above allowing to use a grouping filter with nested object properties (eg. groupBy:'team.id')
export class GroupByValueConverter {
toView(array, groupBy) {
var groups = {};
var props = groupBy.split(".");
array.forEach(function (o) {
var group = o;
props.forEach(function (p) { group = group[p] });
groups[group] = groups[group] || [];
groups[group].push(o);
});
return Object.keys(groups).map(function (group) {
return {
group: group,
values: groups[group],
};
})
}
}
Yet another extension that allows to specify as group an object. It takes a second parameter for specifying the object key to be used as indexer.
eg. - | groupBy:'team':'id' - | groupBy:'projectMember.team':'id'
export class GroupByValueConverter {
toView(array, groupBy, groupByKey) {
var groups = {};
var groupMembers = {};
var props = groupBy.split(".");
array.forEach(function (o) {
var group = o;
props.forEach(function (p) { group = group[p] });
var index = groupByKey && group ? group[groupByKey] : group;
groups[index] = group;
groupMembers[index] = groupMembers[index] || [];
groupMembers[index].push(o);
});
return Object.keys(groups).map(function (index) {
return {
group: groups[index],
values: groupMembers[index],
};
})
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.