it-swarm.com.de

Wie kann ich Daten mit einem Angular-Filter gruppieren?

Ich habe eine Liste von Spielern, die jeweils zu einer Gruppe gehören. Wie kann ich mit einem Filter die Benutzer pro Gruppe auflisten?

[{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'}];

Ich suche nach diesem Ergebnis:

  • team Alpha
    • Gen
  • team Beta
    • George
    • Paula
  • team-Gamma
    • Steve
    • Scruath des 5. Sektors
128
Benny Bottema

Sie können groupBy von angle.filter module verwenden.
Sie können so etwas tun:

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>

ERGEBNIS:
Gruppenname: alpha
* Spieler: Gene
Gruppenname: Beta
* Spieler: George
* Spielerin: Paula
Gruppenname: gamma
* Spieler: Steve
* Spieler: Scruath

UPDATE:jsbin Beachten Sie die grundlegenden Voraussetzungen für die Verwendung von angular.filter. Beachten Sie insbesondere, dass Sie es zu den Abhängigkeiten Ihres Moduls hinzufügen müssen:

(1) Sie können den Winkelfilter mit vier verschiedenen Methoden installieren:

  1. klonen und erstellen Sie dieses Repository
  2. via Bower: Installieren Sie den Winkelfilter mit $ Bower von Ihrem Terminal aus
  3. via npm: Installieren Sie den Winkelfilter $ npm von Ihrem Terminal aus
  4. über cdnjs http://www.cdnjs.com/libraries/angular-filter

(2) Beziehen Sie angle-filter.js (oder angle-filter.min.js) in Ihre index.html ein, nachdem Sie Angular selbst hinzugefügt haben.

(3) Fügen Sie 'angle.filter' zur Liste der Abhängigkeiten Ihres Hauptmoduls hinzu.

172
a8m

Zusätzlich zu den oben genannten akzeptierten Antworten habe ich einen generischen 'groupBy'-Filter mit der Bibliothek undererscore.js erstellt.

JSFiddle (aktualisiert): http://jsfiddle.net/TD7t3/

Der Filter

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

Notieren Sie sich den Aufruf "Memoize". Diese Unterstrichmethode speichert das Ergebnis der Funktion im Cache und verhindert, dass der Filterausdruck jedes Mal von wink ausgewertet wird. Dadurch wird verhindert, dass der Winkel die Digest-Iterationsgrenze erreicht.

Die 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>

Wir wenden unseren Filter 'groupBy' auf die Bereichsvariable teamPlayers und die Eigenschaft 'team' an. Unsere Wiederholungswiederholung erhält eine Kombination aus (Schlüssel, Werte []), die wir in unseren folgenden Iterationen verwenden können.

Update 11. Juni 2014 Ich erweiterte die Gruppe um einen Filter, um die Verwendung von Ausdrücken als Schlüssel zu berücksichtigen (z. B. verschachtelte Variablen). Der Winkelanalysedienst ist dafür sehr praktisch:

Der Filter (mit Ausdrucksunterstützung)

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

Der Controller (mit verschachtelten Objekten)

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}];
});

Das HTML (mit sortBy-Ausdruck)

<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/

24
chrisv

Führen Sie zunächst eine Schleife aus, indem Sie einen Filter verwenden, der nur bestimmte Teams zurückgibt, und dann eine verschachtelte Schleife, die alle Spieler pro aktuelles Team zurückgibt:

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>

skript:

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;
    }
}
19
Benny Bottema

Ich habe ursprünglich die Antwort von Plantface verwendet, aber mir hat die Syntax meiner Ansicht nach nicht gefallen.

Ich habe es überarbeitet, um $ q.defer zu verwenden, um die Daten nachzubearbeiten und eine Liste für eindeutige Teams zurückzugeben, die dann als Filter verwendet wird.

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

Aussicht

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

Regler

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);

});
16
Walter Stabosz

Beide Antworten waren gut, also habe ich sie in eine Direktive verschoben, damit sie wiederverwendet werden kann und eine zweite Gültigkeitsbereichsvariable nicht definiert werden muss.

Hier ist die Geige wenn Sie sehen wollen, dass sie umgesetzt wird

Unten ist die Direktive:

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);
        };
    });

Dann kann es wie folgt verwendet werden:

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

Aktualisieren

Ich habe diese Antwort zunächst geschrieben, weil die alte Version der von Ariel M. vorgeschlagenen Lösung in Kombination mit anderen $filters"Infite $ diggest Loop Error" (infdig) ausgelöst hat. Glücklicherweise wurde dieses Problem in der neuesten Version von angle.filter behoben. 

Ich schlug die folgende Implementierung vor, die das Problem nicht hatte :

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;
    };
});

Diese Implementierung funktioniert jedoch nur mit Versionen vor Angular 1.3. (Ich werde diese Antwort in Kürze aktualisieren und eine Lösung bereitstellen, die mit allen Versionen funktioniert.)

Ich habe tatsächlich einen Beitrag über die Schritte geschrieben, die ich unternommen habe, um diesen $filter zu entwickeln, die Probleme, auf die ich gestoßen bin, und die Dinge, die ich daraus gelernt habe

11
Josep

Zusätzlich zur akzeptierten Antwort können Sie diese verwenden, wenn Sie nach mehreren Spalten gruppieren möchten:

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

Wenn Sie das in js Code brauchen. Sie können die injizierte Methode der Angula-Filter-Lib verwenden. So was.

function controller($scope, $http, groupByFilter) {     

   var groupedData = groupByFilter(originalArray, 'groupPropName');

}

https://github.com/a8m/angular-filter/wiki/Common-Questions#inject-filter

0
trueboroda