How to Group Data with an Angular Filter

How can I group data with an Angular filter?

You can use groupBy of angular.filter module.

so you can do something like this:

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 ng-repeat="(key, value) in players | groupBy: 'team'">
Group name: {{ key }}
<li ng-repeat="player in value">
player: {{ player.name }}
</li>
</ul>

RESULT:

Group name: alpha

* player: Gene

Group name: beta

* player: George

* player: Paula

Group name: gamma

* player: Steve

* player: Scruath

UPDATE: jsbin Remember the basic requirements to use angular.filter, specifically note you must add it to your module's dependencies:

(1) You can install angular-filter using 4 different methods:

  1. clone & build this repository
  2. via Bower: by running $ bower install angular-filter from your terminal
  3. via npm: by running $ npm install angular-filter from your terminal
  4. via cdnjs http://www.cdnjs.com/libraries/angular-filter

(2) Include angular-filter.js (or angular-filter.min.js) in your index.html, after including Angular itself.

(3) Add 'angular.filter' to your main module's list of dependencies.

Filtering and/or grouping data in Angular 5+

The following code is my pure RxJS solution :P

import { from } from 'rxjs';
import { groupBy, mergeMap, map, toArray, tap } from 'rxjs/operators';

let searchResults = [
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo1.jpg", "photoTitle": "Photo1"},
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo2.jpg", "photoTitle": "Photo2"},
{ "id": "rogersfr02", "first": "Fred", "last": "Rogers", "photo": "photo55.jpg", "photoTitle": "Photo55"}
];

from(this.searchResults).pipe(

// Select necessary attributes
map(result => {
//console.log('Result:', result);
let fname = result['first'];
let lname = result['last'];
let photo = result['photoTitle'];
let rname = [fname, lname].join(' ');
return { rname, photo };
}),

// group objects by `rname` attribute
groupBy(result => result['rname']),

// return each item in group as array
mergeMap(group => {
//console.log('Group $1:', group);
return group.pipe(
toArray(),
);
}),

// Reduce arrays of objects
map(group => {
//console.log('Group $2:', JSON.stringify(group));
let rname = group[0]['rname'];
return group.reduce((a, b) => {
return {
rname: rname,
photo: [a.photo, b.photo],
};
});
}),

// Bypass and verify results
tap(result => console.log('Result:', result)),

).subscribe();

How to filter and group the data based on name using angularjs?

Updated

If you can not change the loops in the template, consider the following:

Template

<body ng-app="app" ng-controller="MainCtrl">
<!-- Original loops -->
<div ng-repeat="nameGroup in loopData">
<div ng-repeat="loopData in nameGroup.values track by $index">

<!-- Data name -->
<strong>{{loopData.name}}</strong>

<!-- Loop data descriptions -->
<ul ng-repeat="description in loopData.descriptions">
<li>{{description}}</li>
</ul>

</div>
</div>
</body>

Controller

var app = angular.module('app', ['angular.filter']);

app.controller('MainCtrl', function($scope) {

$scope.loopData = [
{
country: "Abc",
id: "001",
mynumbers: [],
values: [
{ description: "first desc", name: "First Test Name" },
{ description: "second desc", name: "First Test Name" },
{ description: "third desc", name: "First Test Name" },
{ description: "fourth desc", name: "Second Test Name" },
{ description: "fifth desc", name: "Second Test Name" },
{ description: "sixth desc", name: "Third Test Name" },
{ description: "seventh desc", name: "Third Test Name" },
{ description: "eighth desc", name: "Third Test Name" },
{ description: "ninth desc", name: "Third Test Name" },
{ description: "tenth desc", name: "Third Test Name" },
{ description: "eleventh desc", name: "Fourth Test Name" },
{ description: "twelfth desc", name: "Fourth Test Name" }
]
}
];

this.$onInit = function() {
$scope.loopData.forEach(function(data) {
const groupedValues = {};

// group values by name
data.values.forEach(function(value) {
// initialize name group
if (!groupedValues[value.name]) {
groupedValues[value.name] = {
name: value.name,
descriptions: []
};
}

// add description to name group
groupedValues[value.name].descriptions.push(value.description);
});

// update values
data.values = Object.values(groupedValues);
});
};

});

Note that the $onInit function will convert $scope.loopData to the following:

[
{
"country": "Abc",
"id": "001",
"mynumbers": [],
"values": [
{
"name": "First Test Name",
"descriptions": [
"first desc",
"second desc",
"third desc"
]
},
{
"name": "Second Test Name",
"descriptions": [
"fourth desc",
"fifth desc"
]
},
{
"name": "Third Test Name",
"descriptions": [
"sixth desc",
"seventh desc",
"eighth desc",
"ninth desc",
"tenth desc"
]
},
{
"name": "Fourth Test Name",
"descriptions": [
"eleventh desc",
"twelfth desc"
]
}
]
}
]

Original answer

In your html you're not looping on your processed finalLoopData variable. Also, to display the name of the group once, you need to have it in the first loop (not the second).

Consider the following code:

Template

<body ng-app="app" ng-controller="MainCtrl">
<!-- Loop final data -->
<div ng-repeat="nameGroup in finalLoopData">

<!-- Group name -->
<strong>{{nameGroup.name}}</strong>

<!-- Loop group descriptions -->
<ul ng-repeat="description in nameGroup.descriptions track by $index">
<li>{{description}}</li>
</ul>

</div>
</body>

Controller

var app = angular.module('app', ['angular.filter']);

app.controller('MainCtrl', function($scope) {

$scope.finalLoopData = {};

$scope.loopData = [
{
country: "Abc",
id: "001",
mynumbers: [],
values: [
{ description: "first desc", name: "First Test Name" },
{ description: "second desc", name: "First Test Name" },
{ description: "third desc", name: "First Test Name" },
{ description: "fourth desc", name: "Second Test Name" },
{ description: "fifth desc", name: "Second Test Name" },
{ description: "sixth desc", name: "Third Test Name" },
{ description: "seventh desc", name: "Third Test Name" },
{ description: "eighth desc", name: "Third Test Name" },
{ description: "ninth desc", name: "Third Test Name" },
{ description: "tenth desc", name: "Third Test Name" },
{ description: "eleventh desc", name: "Fourth Test Name" },
{ description: "twelfth desc", name: "Fourth Test Name" }
]
}
];

this.$onInit = function() {
const finalLoopData = {};
$scope.loopData[0].values.forEach(function(item) {
// initialize name group
if (!finalLoopData[item.name]) {
finalLoopData[item.name] = {
name: item.name,
descriptions: []
};
}

// add description to name group
finalLoopData[item.name].descriptions.push(item.description);
});

// apply results
$scope.finalLoopData = finalLoopData;
};

});

angular filter - group by object (or multiple fields)

I have a simple solution:

I grouped by team.id

<li ng-repeat="(teamid, players) in players | groupBy: 'team.id'">

Then I used: players[0].team.name within the group

<li ng-repeat="(teamid, players) in players | groupBy: 'team.id'">
<a href="#Here I can use the group teamid">Group name: {{ players[0].team.name }}</a>
<ul>
<li ng-repeat="player in players">
player: {{ player.name }}
</li>
</ul>
</li>

Since players in each group are only the players belonging to this group where all of them have the same team, so players[0], players[1] and so on will have the same team name.

     var app = angular.module('myApp',['angular.filter']);

app.controller('MainController', ['$scope', function($scope){

$scope.players = [

{

name: 'Gene',

team: {

'id' : '1',

'name' : 'alpha'



}

},

{

name: 'George',

team: {

'id' : '2',

'name' : 'beta'

}

},

{

name: 'Steve',

team: {

'id' : '3',

'name' : 'gamma'

}

},

{

name: 'Paula',

team: {

'id' : '2',

'name' : 'beta'

}

},

{

name: 'Scruath',

team: {

'id' : '3',

'name' : 'gamma'

}

}

];

}]);

<!DOCTYPE html>

<html>

<head>

<script data-require="angularjs@1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>

<script data-require="angular-filter@*" data-semver="0.5.7" src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.7/angular-filter.js"></script>

<link rel="stylesheet" href="style.css" />

<script src="script.js"></script>

</head>

<body ng-app="myApp">

<div ng-controller="MainController">

<ul>

<li ng-repeat="(teamid, players) in players | groupBy: 'team.id'">

<a href="#Here I can use the group teamid">Group name: {{ players[0].team.name }}</a>

<ul>

<li ng-repeat="player in players">

player: {{ player.name }}

</li>

</ul>

</li>

</ul>

</div>

</body>

</html>

How can I group data with count of particular item in an Angular filter?

Just add the length of group to HTML like this {{ value.length }} .

<body>
<div ng-controller="MainController">
<ul ng-repeat="(key, value) in players | groupBy: 'team'">
Group name: {{ key }} {{ value.length }}
<li ng-repeat="player in value">
player: {{ player.name }}
</li>
<li>score: {{value | map: 'score' | sum}}</li>
</ul>
</div>
</body>


Related Topics



Leave a reply



Submit