javascript - principiantes - pdf angular js
¿Cómo puedo agrupar datos con un filtro angular? (7)
Actualizar
Inicialmente escribí esta respuesta porque la versión anterior de la solución sugerida por Ariel M. cuando se combinaba con otros $filter
provocaba un " Infite $ diggest Loop Error " ( infdig
) . Afortunadamente, este problema se ha resuelto en la última versión del angular.filter .
Sugerí la siguiente implementación, que no tenía ese problema :
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;
};
});
Sin embargo, esta implementación solo funcionará con versiones anteriores a Angular 1.3. (Actualizaré esta respuesta en breve para proporcionar una solución que funcione con todas las versiones).
Tengo una lista de jugadores que pertenecen a un grupo cada uno. ¿Cómo puedo usar un filtro para enumerar a los usuarios por grupo?
[{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''}];
Estoy buscando este resultado:
- equipo alfa
- Gene
- equipo beta
- Jorge
- Paula
- equipo gamma
- Steve
- Scruath del quinto sector
Además de la respuesta aceptada, puede usar esto si desea agrupar por varias columnas :
<ul ng-repeat="(key, value) in players | groupBy: ''[team,name]''">
Además de las respuestas aceptadas anteriormente, creé un filtro genérico ''groupBy'' utilizando la biblioteca underscore.js.
JSFiddle (actualizado): http://jsfiddle.net/TD7t3/
El filtro
app.filter(''groupBy'', function() {
return _.memoize(function(items, field) {
return _.groupBy(items, field);
}
);
});
Tenga en cuenta la llamada ''memoize''. Este método de subrayado almacena en caché el resultado de la función y deja de angular la evaluación de la expresión de filtro cada vez, evitando así que angular alcance el límite de iteraciones de resumen.
El 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>
Aplicamos nuestro filtro ''groupBy'' en la variable de ámbito teamPlayers, en la propiedad ''team''. Nuestra ng-repeat recibe una combinación de (clave, valores []) que podemos usar en nuestras siguientes iteraciones.
Actualización 11 de junio de 2014 Expandí el grupo por filtro para tener en cuenta el uso de expresiones como la clave (por ejemplo, variables anidadas). El servicio de análisis angular es muy útil para esto:
El filtro (con soporte de expresión)
app.filter(''groupBy'', function($parse) {
return _.memoize(function(items, field) {
var getter = $parse(field);
return _.groupBy(items, function(item) {
return getter(item);
});
});
});
El controlador (con objetos anidados)
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}];
});
El html (con expresión sortBy)
<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/
Ambas respuestas fueron buenas, así que las moví a una directiva para que sea reutilizable y no sea necesario definir una segunda variable de ámbito.
Aquí está el violín si quieres verlo implementado
A continuación está la directiva:
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);
};
});
Luego se puede usar de la siguiente manera:
<div ng-repeat="team in players|groupBy:''team''">
<b>{{team}}</b>
<li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li>
</div>
Originalmente utilicé la respuesta de Plantface, pero no me gustó cómo se veía la sintaxis en mi opinión.
Lo volví a trabajar para usar $q.defer para postprocesar los datos y devolver una lista en equipos únicos, que luego se usa como filtro.
http://plnkr.co/edit/waWv1donzEMdsNMlMHBa?p=preview
Ver
<ul>
<li ng-repeat="team in teams">{{team}}
<ul>
<li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li>
</ul>
</li>
</ul>
Controlador
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);
});
Primero haz un bucle usando un filtro que devolverá solo equipos únicos, y luego un bucle anidado que devuelve todos los jugadores por equipo actual:
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>
guión:
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;
}
}
Puede usar groupBy of angular.filter module.
para que pueda hacer algo como esto:
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>
RESULTADO:
Nombre del grupo: alfa
* jugador: Gene
Nombre del grupo: beta
* jugador: George
* jugador: Paula
Nombre del grupo: gamma
* jugador: Steve
* jugador: Scruath
ACTUALIZACIÓN: jsbin Recuerde los requisitos básicos para usar angular.filter
, específicamente tenga en cuenta que debe agregarlo a las dependencias de su módulo:
(1) Puede instalar un filtro angular usando 4 métodos diferentes:
- clonar y construir este repositorio
- a través de Bower: ejecutando $ bower install angular-filter desde tu terminal
- via npm: ejecutando $ npm instalar filtro angular desde su terminal
- via cdnjs http://www.cdnjs.com/libraries/angular-filter
(2) Incluya angular-filter.js (o angular-filter.min.js) en su index.html, después de incluir Angular.
(3) Agregue ''angular.filter'' a la lista de dependencias de su módulo principal.