Fonction de sorting personnalisée dans ng-repeat

J’ai un ensemble de tuiles qui affichent un certain nombre en fonction de l’option sélectionnée par l’utilisateur. Je voudrais maintenant mettre en œuvre un sorting quel que soit le nombre affiché.

Le code ci-dessous montre comment je l’ai implémenté (en obtenant / définissant une valeur dans la scope de la carte parent). Maintenant, comme la fonction orderBy prend une chaîne, j’ai essayé de définir une variable dans l’étendue de la carte appelée curOptionValue et de la sortinger, mais cela ne semble pas fonctionner.

Donc, la question devient, comment créer une fonction de sorting personnalisée?

{{card.name}}

{{getOption()}}

et contrôleur:

 module.controller('aggViewport',['$scope','$location',function($scope,$location) { $scope.cards = [ {name: card1, values: {opt1: 9, opt2: 10}}, {name: card1, values: {opt1: 9, opt2: 10}} ]; $scope.option = "opt1"; $scope.setOption = function(val){ $scope.option = val; } }]); module.controller('aggCardController',['$scope',function($scope){ $scope.getOption = function(){ return $scope.card.values[$scope.option]; } }]); 

En fait, le filtre orderBy peut prendre comme paramètre non seulement une chaîne mais aussi une fonction. De la documentation orderBy : http://docs.angularjs.org/api/ng.filter:orderBy ):

fonction: fonction Getter. Le résultat de cette fonction sera sortingé en utilisant l’opérateur < , =,>.

Donc, vous pourriez écrire votre propre fonction. Par exemple, si vous souhaitez comparer des cartes basées sur une sum de opt1 et opt2 (je le fais, le fait est que vous pouvez avoir n’importe quelle fonction arbitraire), vous écrivez dans votre contrôleur:

 $scope.myValueFunction = function(card) { return card.values.opt1 + card.values.opt2; }; 

et ensuite, dans votre modèle:

 ng-repeat="card in cards | orderBy:myValueFunction" 

Voici le jsFiddle de travail

L’autre chose à noter est que orderBy n’est qu’un exemple des filtres AngularJS, donc si vous avez besoin d’un comportement de commande très spécifique, vous pouvez écrire votre propre filtre (bien que orderBy soit suffisant pour la plupart des cas).

La solution acceptée ne fonctionne que sur les tableaux, mais pas sur les objects ou les tableaux associatifs. Malheureusement, puisque Angular dépend de l’implémentation JavaScript de l’énumération de tableaux, l’ordre des propriétés des objects ne peut pas être contrôlé de manière cohérente. Certains navigateurs peuvent parcourir les propriétés de l’object lexicographiquement, mais cela ne peut pas être garanti.

Par exemple, compte tenu de la tâche suivante:

 $scope.cards = { "card2": { values: { opt1: 9, opt2: 12 } }, "card1": { values: { opt1: 9, opt2: 11 } } }; 

et la directive

    , ng-repeat peut parcourir “card1” avant “card2”, quel que soit l’ordre de sorting.

    Pour contourner ce problème, nous pouvons créer un filtre personnalisé pour convertir l’object en un tableau, puis appliquer une fonction de sorting personnalisée avant de renvoyer la collection.

     myApp.filter('orderByValue', function () { // custom value function for sorting function myValueFunction(card) { return card.values.opt1 + card.values.opt2; } return function (obj) { var array = []; Object.keys(obj).forEach(function (key) { // inject key into each object so we can refer to it from the template obj[key].name = key; array.push(obj[key]); }); // apply a custom sorting function array.sort(function (a, b) { return myValueFunction(b) - myValueFunction(a); }); return array; }; }); 

    Nous ne pouvons pas parcourir les couplages (clés, valeurs) conjointement avec des filtres personnalisés (puisque les clés des tableaux sont des index numériques), le modèle doit donc être mis à jour pour référencer les noms de clés injectés.

     
    • {{card.name}} {{value(card)}}

    Voici un violon de travail utilisant un filtre personnalisé sur un tableau associatif: http://jsfiddle.net/av1mLpqx/1/

    Référence: https://github.com/angular/angular.js/issues/1286#issuecomment-22193332

    Le lien suivant explique extrêmement bien les filtres dans Angular. Il montre comment il est possible de définir une logique de sorting personnalisée dans une ng-repeat. http://toddmotto.com/everything-about-custom-filters-in-angular-js

    Pour le sorting d’object avec des propriétés, il s’agit du code que j’ai utilisé: (Notez que ce sorting est la méthode de sorting JavaScript standard et non spécifique à un angle). Nom de la colonne est le nom de la propriété sur laquelle le sorting doit être effectué.

     self.myArray.sort(function(itemA, itemB) { if (self.sortOrder === "ASC") { return itemA[columnName] > itemB[columnName]; } else { return itemA[columnName] < itemB[columnName]; } });