92 votes

AngularJS : tri par propriété

Ce que j'essaie de faire, c'est de trier des données par propriété. Voici un exemple qui devrait fonctionner mais qui ne fonctionne pas.

Partie HTML :

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="(key, value) in testData | orderBy:'value.order'">
            {{value.order}}. {{key}} -> {{value.name}}
        </li>
    </ul>
    </div>
</div>

Partie JS :

var myApp = angular.module('myApp', []);

myApp.controller('controller', ['$scope', function ($scope) {

    $scope.testData = {
        C: {name:"CData", order: 1},
        B: {name:"BData", order: 2},
        A: {name:"AData", order: 3},
    }

}]);

Et le résultat :

  1. A -> AData
  2. B -> Données BD
  3. C -> CData

... qui, selon moi, devrait ressembler à ceci :

  1. C -> CData
  2. B -> Données BD
  3. A -> AData

J'ai raté quelque chose (voici le prêt JSFiddle à expérimenter) ?

146voto

Armin Points 3308

Le filtre orderBy d'AngularJS ne prend en charge que les tableaux, pas les objets. Vous devez donc écrire votre propre petit filtre, qui effectue le tri à votre place.

Ou changez le format des données que vous traitez (si vous avez une influence sur ce point). Un tableau contenant des objets est triable par le filtre natif orderBy.

Voici mon orderObjectBy pour AngularJS :

app.filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });
    return array;
 }
});

Utilisation selon votre point de vue :

<div class="item" ng-repeat="item in items | orderObjectBy:'position'">
    //...
</div>

L'objet a besoin dans cet exemple d'un attribut de position, mais vous avez la possibilité d'utiliser n'importe quel attribut dans les objets (contenant un entier), juste par définition dans la vue.

Exemple JSON :

{
    "123": {"name": "Test B", "position": "2"},
    "456": {"name": "Test A", "position": "1"}
}

Voici un fiddle qui vous montre l'utilisation : http://jsfiddle.net/4tkj8/1/

31voto

Leon Points 403

C'est assez facile, faites comme ça.

$scope.props = [{order:"1"},{order:"5"},{order:"2"}]

ng-repeat="prop in props | orderBy:'order'"

7voto

Eric Steinborn Points 126

N'oubliez pas que parseInt() ne fonctionne que pour les valeurs entières. Pour trier des valeurs de type chaîne de caractères, vous devez intervertir ceci :

array.sort(function(a, b){
  a = parseInt(a[attribute]);
  b = parseInt(b[attribute]);
  return a - b;
});

avec ça :

array.sort(function(a, b){
  var alc = a[attribute].toLowerCase(),
      blc = b[attribute].toLowerCase();
  return alc > blc ? 1 : alc < blc ? -1 : 0;
});

6voto

SunnyShah Points 4088

Comme vous pouvez le voir dans le code d'angular-JS ( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js ) ng-repeat ne fonctionne pas avec les objets. Voici un hack avec sortFunction.

http://jsfiddle.net/sunnycpp/qaK56/33/

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="test in testData | orderBy:sortMe()">
            Order = {{test.value.order}} -> Key={{test.key}} Name=:{{test.value.name}}
        </li>
    </ul>
    </div>
</div>

myApp.controller('controller', ['$scope', function ($scope) {

    var testData = {
        a:{name:"CData", order: 2},
        b:{name:"AData", order: 3},
        c:{name:"BData", order: 1}
    };
    $scope.testData = _.map(testData, function(vValue, vKey) {
        return { key:vKey, value:vValue };
    }) ;
    $scope.sortMe = function() {
        return function(object) {
            return object.value.order;
        }
    }
}]);

4voto

Gal Ben-Haim Points 5702

En fonction de http://docs.angularjs.org/api/ng.filter:orderBy orderBy trie un tableau. Dans votre cas, vous passez un objet, vous devrez donc implémenter votre propre fonction de tri.

ou passer un tableau -

$scope.testData = {
    C: {name:"CData", order: 1},
    B: {name:"BData", order: 2},
    A: {name:"AData", order: 3},
}

jeter un coup d'œil à http://jsfiddle.net/qaK56/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X