En plus des réponses acceptées ci-dessus, j'ai créé un filtre générique 'groupBy' en utilisant la bibliothèque underscore.js.
JSFiddle (mis à jour):
http://jsfiddle.net/TD7t3/
Le filtre
app.filter('groupBy', function() {
return _.memoize(function(items, field) {
return _.groupBy(items, field);
}
);
});
Notez l'appel «mémoize». Cette méthode de soulignement met en cache le résultat de la fonction et empêche angular d'évaluer l'expression du filtre à chaque fois, empêchant ainsi angular d'atteindre la limite d'itérations de résumé.
Le 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>
Nous appliquons notre filtre 'groupBy' sur la variable de portée teamPlayers, sur la propriété 'team'. Notre ng-repeat reçoit une combinaison de (clé, valeurs []) que nous pouvons utiliser dans nos itérations suivantes.
Mise à jour du 11 juin 2014
J'ai élargi le groupe par filtre pour tenir compte de l'utilisation d'expressions comme clé (par exemple des variables imbriquées). Le service d'analyse angulaire est très pratique pour cela:
Le filtre (avec support d'expression)
app.filter('groupBy', function($parse) {
return _.memoize(function(items, field) {
var getter = $parse(field);
return _.groupBy(items, function(item) {
return getter(item);
});
});
});
Le contrôleur (avec des objets imbriqués)
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}];
});
Le html (avec l'expression 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/