如何使用Angularfilter对数据进行分组?

我有一个属于一个组的球员名单。 我如何使用filter列出每个用户的用户?

[{name: 'Gene', team: 'team alpha'}, {name: 'George', team: 'team beta'}, {name: 'Steve', team: 'team gamma'}, {name: 'Paula', team: 'team beta'}, {name: 'Scruath of the 5th sector', team: 'team gamma'}]; 

我正在寻找这个结果:

  • 队阿尔法
    • 基因
  • 队testing
    • 乔治
  • 团队伽马
    • 史蒂夫
    • 第五部分的成熟

你可以使用angular.filter模块的groupBy 。
所以你可以做这样的事情:

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> 

结果:
组名:alpha
*球员:基因
组名:beta
*球员:乔治
*球员:宝拉
组名:伽马
*球员:史蒂夫
*播放器:Scruath

更新: jsbin记住使用angular.filter的基本要求,特别要注意的是你必须把它添加到你的模块的依赖项中:

(1)您可以使用4种不同的方法安装angular度filter:

  1. 克隆和build立这个存储库
  2. 通过鲍尔:通过从terminal运行$ bower安装angular度filter
  3. 通过npm:从terminal运行$ npm install angular-filter
  4. 通过cdnjs http://www.cdnjs.com/libraries/angular-filter

(2)在包含Angular本身之后,在你的index.html中包含angular-filter.js(或者angular-filter.min.js)。

(3)将'angular.filter'添加到主模块的依赖关系列表中。

除了上面所接受的答案之外,我使用underscore.js库创build了一个通用的“groupBy”filter。

JSFiddle(更新): http : //jsfiddle.net/TD7t3/

filter

 app.filter('groupBy', function() { return _.memoize(function(items, field) { return _.groupBy(items, field); } ); }); 

请注意“memoize”调用。 该下划线方法caching该函数的结果,并且每次都从评估filterexpression式来停止angular度,从而防止angular度达到摘要迭代限制。

html

 <ul> <li ng-repeat="(team, players) in teamPlayers | groupBy:'team'"> {{team}} <ul> <li ng-repeat="player in players"> {{player.name}} </li> </ul> </li> </ul> 

我们将'groupBy'filter应用于teamPlayers范围variables的'team'属性上。 我们的ng-repeat接收(我们可以在下面的迭代中使用的(key,values [])的组合。

更新2014年6月11日我通过filter扩展了组,以说明使用expression式作为键(例如嵌套variables)。 angular度分析服务非常方便:

filter(带expression式支持)

 app.filter('groupBy', function($parse) { return _.memoize(function(items, field) { var getter = $parse(field); return _.groupBy(items, function(item) { return getter(item); }); }); }); 

控制器(嵌套对象)

 app.controller('homeCtrl', function($scope) { var teamAlpha = {name: 'team alpha'}; var teamBeta = {name: 'team beta'}; var teamGamma = {name: 'team gamma'}; $scope.teamPlayers = [{name: 'Gene', team: teamAlpha}, {name: 'George', team: teamBeta}, {name: 'Steve', team: teamGamma}, {name: 'Paula', team: teamBeta}, {name: 'Scruath of the 5th sector', team: teamGamma}]; }); 

html(用sortByexpression式)

 <li ng-repeat="(team, players) in teamPlayers | groupBy:'team.name'"> {{team}} <ul> <li ng-repeat="player in players"> {{player.name}} </li> </ul> </li> 

JSFiddle: http : //jsfiddle.net/k7fgB/2/

首先做一个循环,使用只返回唯一团队的filter,然后是一个嵌套循环,每个当前团队返回所有玩家:

http://jsfiddle.net/plantface/L6cQN/

HTML:

 <div ng-app ng-controller="Main"> <div ng-repeat="playerPerTeam in playersToFilter() | filter:filterTeams"> <b>{{playerPerTeam.team}}</b> <li ng-repeat="player in players | filter:{team: playerPerTeam.team}">{{player.name}}</li> </div> </div> 

脚本:

 function Main($scope) { $scope.players = [{name: 'Gene', team: 'team alpha'}, {name: 'George', team: 'team beta'}, {name: 'Steve', team: 'team gamma'}, {name: 'Paula', team: 'team beta'}, {name: 'Scruath of the 5th sector', team: 'team gamma'}]; var indexedTeams = []; // this will reset the list of indexed teams each time the list is rendered again $scope.playersToFilter = function() { indexedTeams = []; return $scope.players; } $scope.filterTeams = function(player) { var teamIsNew = indexedTeams.indexOf(player.team) == -1; if (teamIsNew) { indexedTeams.push(player.team); } return teamIsNew; } } 

我最初使用Plantface的答案,但我不喜欢在我看来的语法。

我重写了它,使用$ q.defer来后处理数据,并在唯一的团队上返回一个列表,然后用作filter。

http://plnkr.co/edit/waWv1donzEMdsNMlMHBa?p=preview

视图

 <ul> <li ng-repeat="team in teams">{{team}} <ul> <li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li> </ul> </li> </ul> 

调节器

 app.controller('MainCtrl', function($scope, $q) { $scope.players = []; // omitted from SO for brevity // create a deferred object to be resolved later var teamsDeferred = $q.defer(); // return a promise. The promise says, "I promise that I'll give you your // data as soon as I have it (which is when I am resolved)". $scope.teams = teamsDeferred.promise; // create a list of unique teams. unique() definition omitted from SO for brevity var uniqueTeams = unique($scope.players, 'team'); // resolve the deferred object with the unique teams // this will trigger an update on the view teamsDeferred.resolve(uniqueTeams); }); 

两个答案都很好,所以我把它们移到了一个指令中,这样它就可以重用,而第二个作用域variables也不需要定义。

这里是小提琴,如果你想看到它的实施

以下是指令:

 var uniqueItems = function (data, key) { var result = []; for (var i = 0; i < data.length; i++) { var value = data[i][key]; if (result.indexOf(value) == -1) { result.push(value); } } return result; }; myApp.filter('groupBy', function () { return function (collection, key) { if (collection === null) return; return uniqueItems(collection, key); }; }); 

那么它可以使用如下:

 <div ng-repeat="team in players|groupBy:'team'"> <b>{{team}}</b> <li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li> </div> 

更新

我最初编写这个答案是因为Ariel M.提出的解决scheme的旧版本与其他$filter结合触发了“ Infite $ diggest Loop Error ”( infdig ) 。 幸运的是,这个问题已经在angular.filter的最新版本中得到了解决。

我build议下面的实现, 没有这个问题 :

 angular.module("sbrpr.filters", []) .filter('groupBy', function () { var results={}; return function (data, key) { if (!(data && key)) return; var result; if(!this.$id){ result={}; }else{ var scopeId = this.$id; if(!results[scopeId]){ results[scopeId]={}; this.$on("$destroy", function() { delete results[scopeId]; }); } result = results[scopeId]; } for(var groupKey in result) result[groupKey].splice(0,result[groupKey].length); for (var i=0; i<data.length; i++) { if (!result[data[i][key]]) result[data[i][key]]=[]; result[data[i][key]].push(data[i]); } var keys = Object.keys(result); for(var k=0; k<keys.length; k++){ if(result[keys[k]].length===0) delete result[keys[k]]; } return result; }; }); 

但是,这个实现只适用于Angular 1.3之前的版本。 (我会尽快更新这个答案,提供适用于所有版本的解决scheme。)

其实我写了一篇关于我开发这个$filter的步骤,我遇到的问题以及从中学到的东西 。

除了被接受的答案之外,如果您想按多列进行分组,则可以使用这个答案:

 <ul ng-repeat="(key, value) in players | groupBy: '[team,name]'">