Ben*_*ema 135 javascript grouping filter angularjs
我有一个属于一个组的玩家列表.如何使用过滤器列出每组用户?
[{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'}];
Run Code Online (Sandbox Code Playgroud)
我正在寻找这个结果:
a8m*_*a8m 179
您可以使用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'}
];
Run Code Online (Sandbox Code Playgroud)
HTML:
<ul ng-repeat="(key, value) in players | groupBy: 'team'">
Group name: {{ key }}
<li ng-repeat="player in value">
player: {{ player.name }}
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
结果:
组名:alpha
*player:Gene
组名:beta
*球员:George
*球员:Paula
组名:gamma
*球员:Steve
*球员:Scruath
更新: jsbin记住要使用的基本要求angular.filter
,特别注意你必须将它添加到模块的依赖项中:
(1)您可以使用4种不同的方法安装角度滤波器:
- 克隆并构建此存储库
- 通过Bower:从您的终端运行$ bower install angular-filter
- 通过npm:从您的终端运行$ npm install angular-filter
- 通过cdnjs http://www.cdnjs.com/libraries/angular-filter
(2)在包含Angular本身之后,在index.html中包含angular-filter.js(或angular-filter.min.js).
(3)将'angular.filter'添加到主模块的依赖项列表中.
chr*_*isv 24
除了上面接受的答案之外,我还使用underscore.js库创建了一个通用的"groupBy"过滤器.
JSFiddle(更新):http: //jsfiddle.net/TD7t3/
过滤器
app.filter('groupBy', function() {
return _.memoize(function(items, field) {
return _.groupBy(items, field);
}
);
});
Run Code Online (Sandbox Code Playgroud)
请注意'memoize'调用.该下划线方法缓存函数的结果并且每次都停止角度评估过滤器表达式,从而防止角度达到摘要迭代限制.
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>
Run Code Online (Sandbox Code Playgroud)
我们在'team'属性的teamPlayers范围变量上应用'groupBy'过滤器.我们的ng-repeat接收到(key,values [])的组合,我们可以在以下迭代中使用它们.
更新2014年6月11日 我通过过滤器扩展了组,以便将表达式用作关键(例如嵌套变量).角度解析服务非常方便:
过滤器(带表达式支持)
app.filter('groupBy', function($parse) {
return _.memoize(function(items, field) {
var getter = $parse(field);
return _.groupBy(items, function(item) {
return getter(item);
});
});
});
Run Code Online (Sandbox Code Playgroud)
控制器(带嵌套对象)
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}];
});
Run Code Online (Sandbox Code Playgroud)
html(带sortBy表达式)
<li ng-repeat="(team, players) in teamPlayers | groupBy:'team.name'">
{{team}}
<ul>
<li ng-repeat="player in players">
{{player.name}}
</li>
</ul>
</li>
Run Code Online (Sandbox Code Playgroud)
JSFiddle:http: //jsfiddle.net/k7fgB/2/
Ben*_*ema 19
首先使用仅返回唯一团队的过滤器进行循环,然后使用嵌套循环返回每个当前团队的所有玩家:
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>
Run Code Online (Sandbox Code Playgroud)
脚本:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Wal*_*osz 16
我最初使用了Plantface的答案,但我不喜欢语法在我看来的样子.
我重新设计它以使用$ q.defer对数据进行后处理并返回唯一团队的列表,然后将其用作过滤器.
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>
Run Code Online (Sandbox Code Playgroud)
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);
});
Run Code Online (Sandbox Code Playgroud)
The*_*heo 11
两个答案都很好,所以我将它们移动到一个指令中,以便它可以重用,并且不必定义第二个范围变量.
如果你想看到它的实现,这是小提琴
以下是指令:
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);
};
});
Run Code Online (Sandbox Code Playgroud)
然后它可以使用如下:
<div ng-repeat="team in players|groupBy:'team'">
<b>{{team}}</b>
<li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li>
</div>
Run Code Online (Sandbox Code Playgroud)
Jos*_*sep 11
我最初写的这个答案是因为Ariel M. 在与其他$filter
s 组合时提出的旧版解决方案触发了" Infite $ diggest Loop Error "(infdig
).幸运的是,这个问题已在最新版本的angular.filter中得到解决.
我建议以下实现,没有这个问题:
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;
};
});
Run Code Online (Sandbox Code Playgroud)
但是,此实现仅适用于Angular 1.3之前的版本.(我将在短期内更新此答案,提供适用于所有版本的解决方案.)
我实际上写过一篇文章,讲述了我为此制定的步骤$filter
,我遇到的问题以及从中学到的东西.
归档时间: |
|
查看次数: |
148001 次 |
最近记录: |