ng-répétition angulaire en sens inverse

227

Comment puis-je obtenir un tableau inversé en angulaire? j'essaie d'utiliser le filtre orderBy, mais il a besoin d'un prédicat (par exemple 'nom') pour trier:

<tr ng-repeat="friend in friends | orderBy:'name':true">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
<tr>

Existe-t-il un moyen d'inverser le tableau d'origine, sans trier. comme ça:

<tr ng-repeat="friend in friends | orderBy:'':true">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
<tr>
Delremm
la source
4
Ceci est la nouvelle et bonne façon stackoverflow.com/a/16261373/988830
om471987
@QuiteNothing C'est la bonne façon si vous voulez inverser un tableau avec une expression. Dans ce cas, la question était de savoir comment vénérer un tableau sans un.
JayQuerie.com
<tr ng-repeat = "friend in friends | orderBy: '- name'">
desmati
Voir ma réponse ci-dessous pour la ligne simple 1 et la solution correcte. Il n'est pas nécessaire de faire de méthodes. Je me demande pourquoi les gens font des méthodes supplémentaires pour cela.
Muhammad Hassam
Utilisez toujours des filtres pour changer le ng-repeatcomportement! @Trevor Senior a fait du bon travail.
Amir Savand

Réponses:

329

Je suggère d'utiliser un filtre personnalisé comme celui-ci:

app.filter('reverse', function() {
  return function(items) {
    return items.slice().reverse();
  };
});

Qui peut ensuite être utilisé comme:

<div ng-repeat="friend in friends | reverse">{{friend.name}}</div>

Voyez-le fonctionner ici: Démonstration de Plunker


Ce filtre peut être personnalisé pour répondre à vos besoins comme bon vous semble. J'ai fourni d'autres exemples dans la démonstration. Certaines options incluent la vérification que la variable est un tableau avant d'effectuer l'inverse, ou la rendre plus indulgente pour permettre l'inversion de plus de choses telles que des chaînes.

JayQuerie.com
la source
21
Agréable! Sachez simplement que vous items.reverse()modifiez le tableau au lieu d'en créer un nouveau et de le renvoyer.
Anders Ekdahl
12
Merci! J'avais oublié ça. J'ai ajouté un slice()pour résoudre ce problème.
JayQuerie.com
9
Vous devez ajouter if (!angular.isArray(items)) return false;pour vérifier que vous disposez d'un tableau avant d'essayer de le renverser.
respectTheCode
6
Besoin d'être plus défensif contre null, devrait utiliser à la place: retourner les articles? items.slice (). reverse (): [];
Chris Yeung
5
@Chris Yeung: Il n'est pas conseillé de renvoyer un "[]" vide lorsqu'il est nul. Mieux vaut retourner la valeur d'origine.
Siva
202

C'est ce que j'ai utilisé:

<alert ng-repeat="alert in alerts.slice().reverse()" type="alert.type" close="alerts.splice(index, 1)">{{$index + 1}}: {{alert.msg}}</alert>

Mettre à jour:

Ma réponse était OK pour l'ancienne version d'Angular. Maintenant, vous devriez utiliser

ng-repeat="friend in friends | orderBy:'-'"

ou

ng-repeat="friend in friends | orderBy:'+':true"

depuis https://stackoverflow.com/a/26635708/1782470

amit bakle
la source
Uing track by, c'est la seule façon qui a fonctionné pour moi
@delboud vous devriez utiliser la piste après la commandePar:ng-repeat="friend in friends | orderBy:'+': true track by $index"
Vibhum Bhardwaj
125

Désolé d'avoir soulevé cette question après un an, mais il existe une nouvelle solution plus simple , qui fonctionne pour Angular v1.3.0-rc.5 et versions ultérieures .

Il est mentionné dans la documentation : "Si aucune propriété n'est fournie, (par exemple '+'), alors l'élément de tableau lui-même est utilisé pour comparer le tri". La solution sera donc:

ng-repeat="friend in friends | orderBy:'-'" ou

ng-repeat="friend in friends | orderBy:'+':true"

Cette solution semble être meilleure car elle ne modifie pas un tableau et ne nécessite pas de ressources de calcul supplémentaires (au moins dans notre code). J'ai lu toutes les réponses existantes et je leur préfère toujours celle-ci.

Dmitry Gonchar
la source
1
Merci pour le conseil! Pour prévenir toute personne lisant ceci, il semble que cela ne fonctionne pas dans rc4 ( v1.3.0-rc.4). Si quelqu'un a la chance de l'essayer dans la nouvelle version, faites-le nous savoir!
mikermcneil
1
@mikermcneil Merci pour le commentaire! Selon la même documentation, il devrait fonctionner à partir de la v1.3.0-rc.5( documentation rc.5 vs documentation rc.4 ). J'ai mis à jour la réponse
Dmitry Gonchar
1
Ne fonctionne pas pour moi (v1.3.5). Essayé orderBy:'+':true, orderBy:'-':true, orderBy:'-':false, orderBy:'+':false:(
Cody
2
@Cody Désolé pour la réponse tardive. Voilà - un exemple de travail avec angulaire v1.3.5 jsfiddle.net/dmitry_gonchar/L98foxhm/1 . Le problème était probablement ailleurs.
Dmitry Gonchar
1
@alevkon True. Mais cela fonctionne si vous spécifiez le champ ('+ id', '-id' fe). Peut-être que c'est un bogue dans Angular, qu'il ne fonctionne pas avec un ordre normal si vous ne spécifiez pas de champ? J'ai pris cette méthode dans la documentation (le lien est dans la réponse), donc j'ai été surpris aussi bien que vous. Quoi qu'il en soit, la question était de savoir comment inverser un tableau.
Dmitry Gonchar
54

Vous pouvez inverser par le paramètre $ index

<tr ng-repeat="friend in friends | orderBy:'$index':true">
jjhrms
la source
13
Devrait fonctionner, mais ne fonctionne pas (essayé avec et sans guillemets $index). Je suis sur Angular 1.1.5.
Ingénieur
2
A travaillé pour moi (utilisait une propriété pour le tri au lieu de $ index cependant) stackoverflow.com/questions/16261348/…
Certs
4
Ne fonctionne pas avec AngularJS 1.2.13. J'ai modifié mon tableau d'objets pour ajouter un identifiant à chaque objet. L'id étant l'index de l'objet à l'intérieur du tableau. Fonctionne ensuite ng-repeat="friend in friends | orderBy:'id':true".
tanguy_k
51

Solution simple: - (pas besoin de faire de méthodes)

ng-repeat = "friend in friends | orderBy: reverse:true"
Muhammad Hassam
la source
2
Fonctionne très bien pour moi. Merci!
HankScorpio
17

Vous pouvez simplement appeler une méthode sur votre portée pour l'inverser pour vous, comme ceci:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
    <script>
    angular.module('myApp', []).controller('Ctrl', function($scope) {
        $scope.items = [1, 2, 3, 4];
        $scope.reverse = function(array) {
            var copy = [].concat(array);
            return copy.reverse();
        }
    });
    </script>
</head>
<body ng-controller="Ctrl">
    <ul>
        <li ng-repeat="item in items">{{item}}</li>
    </ul>
    <ul>
        <li ng-repeat="item in reverse(items)">{{item}}</li>
    </ul>
</body>
</html>

Notez que le $scope.reversecrée une copie du tableau depuis Array.prototype.reversemodifie le tableau d'origine.

Anders Ekdahl
la source
13

si vous utilisez 1.3.x, vous pouvez utiliser ce qui suit

{{ orderBy_expression | orderBy : expression : reverse}}

Exemple Liste des livres par date de publication dans l'ordre décroissant

<div ng-repeat="book in books|orderBy:'publishedDate':true">

source: https://docs.angularjs.org/api/ng/filter/orderBy

Kumar
la source
11

Si vous utilisez angularjs version 1.4.4 et supérieure , un moyen simple de trier est d'utiliser " $ index ".

 <ul>
  <li ng-repeat="friend in friends|orderBy:$index:true">{{friend.name}}</li>
</ul>

voir la démo

vishnu
la source
1

Lorsque vous utilisez MVC dans .NET avec Angular, vous pouvez toujours utiliser OrderByDecending () lorsque vous effectuez votre requête db comme ceci:

var reversedList = dbContext.GetAll().OrderByDecending(x => x.Id).ToList();

Ensuite, du côté angulaire, il sera déjà inversé dans certains navigateurs (IE). Lors de la prise en charge de Chrome et FF, vous devrez ensuite ajouter orderBy:

<tr ng-repeat="item in items | orderBy:'-Id'">

Dans cet exemple, vous devez trier par ordre décroissant sur la propriété .Id. Si vous utilisez la pagination, cela devient plus compliqué car seule la première page serait triée. Vous devez gérer cela via un fichier de filtre .js pour votre contrôleur, ou d'une autre manière.

pourquoi
la source
0

Vous pouvez également utiliser .reverse (). C'est une fonction de tableau natif

<div ng-repeat="friend in friends.reverse()">{{friend.name}}</div>

Pian0_M4n
la source
Votre vote négatif ne peut signifier qu'une chose: vous avez plus de données entrantes. Si le {} ou le [] continue de recevoir des données, il s'inversera à chaque fois, évidemment. C'est un nouveau résumé
Pian0_M4n
Avertissement pour celui qui veut utiliser ceci: reverseinverse le tableau en place, il ne renvoie pas seulement une copie inversée. Cela signifie que chaque fois que cela est évalué, le tableau est inversé.
jcaron
0

C'est parce que vous utilisez un objet JSON. Lorsque vous rencontrez de tels problèmes, changez votre objet JSON en objet tableau JSON.

Par exemple,

{"India":"IN","America":"US","United Kingdon":"UK"} json object
[{"country":"India","countryId":"IN"},{"country":"America","countryId":"US"},{"country":"United Kingdon","countryId":"UK"}] 
user5891403
la source
0

Le orderByfiltre effectue un tri stable à partir d'Angular 1.4.5. (Voir la demande d'extraction GitHub https://github.com/angular/angular.js/pull/12408 .)

Il suffit donc d'utiliser un prédicat constant et reversedéfini sur true:

<div ng-repeat="friend in friends | orderBy:0:true">{{friend.name}}</div>
user1012976
la source
0

J'ai trouvé quelque chose comme ça, mais au lieu d'un tableau, j'utilise des objets.

Voici ma solution pour les objets:

Ajouter un filtre personnalisé:

app.filter('orderObjectBy', function() {
    return function(items, field, reverse){

        var strRef = function (object, reference) {
            function arr_deref(o, ref, i) {
                return !ref ? o : (o[ref.slice(0, i ? -1 : ref.length)]);
            }
            function dot_deref(o, ref) {
                return !ref ? o : ref.split('[').reduce(arr_deref, o);
            }
            return reference.split('.').reduce(dot_deref, object);
        };

        var filtered = [];

        angular.forEach(items, function(item) {
           filtered.push(item);
        });
        filtered.sort(function (a, b) {
           return (strRef(a, field) > strRef(a, field) ? 1 : -1);
        });
        if(reverse) filtered.reverse();
        return filtered;
    };
});

Qui peut ensuite être utilisé comme

<div ng-repeat="(key, value) in items | orderObjectBy:'field.any.deep':true">

Si vous avez besoin de la prise en charge d'un ancien navigateur, vous devrez définir la fonction de réduction (ceci n'est disponible que dans ECMA-262 mozilla.org )

// Production steps of ECMA-262, Edition 5, 15.4.4.21
// Reference: http://es5.github.io/#x15.4.4.21
if (!Array.prototype.reduce) {
Array.prototype.reduce = function(callback /*, initialValue*/) {
'use strict';
  if (this == null) {
    throw new TypeError('Array.prototype.reduce called on null or undefined');
  }
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  var t = Object(this), len = t.length >>> 0, k = 0, value;
  if (arguments.length == 2) {
    value = arguments[1];
  } else {
    while (k < len && !(k in t)) {
      k++; 
    }
    if (k >= len) {
      throw new TypeError('Reduce of empty array with no initial value');
    }
    value = t[k++];
  }
  for (; k < len; k++) {
    if (k in t) {
      value = callback(value, t[k], k, t);
    }
  }
  return value;
};
}
Twois
la source
0

J'étais moi-même frustré par ce problème et j'ai donc modifié le filtre créé par @Trevor Senior alors que je rencontrais un problème avec ma console en disant qu'elle ne pouvait pas utiliser la méthode inverse. J'ai également voulu garder l'intégrité de l'objet car c'est ce qu'Angular utilise à l'origine dans une directive ng-repeat. Dans ce cas, j'ai utilisé l'entrée stupide (clé) car la console va se fâcher en disant qu'il y a des doublons et dans mon cas, j'avais besoin de suivre par $ index.

Filtre:

angular.module('main').filter('reverse', function() {
    return function(stupid, items) {
    var itemss = items.files;
    itemss = itemss.reverse();  
    return items.files = itemss; 
  };
});

HTML: <div ng-repeat="items in items track by $index | reverse: items">

Conteneur codé
la source
0

J'ajoute une réponse que personne n'a mentionnée. J'essaierais de faire le serveur si vous en avez un. Le filtrage côté client peut être dangereux si le serveur renvoie de nombreux enregistrements. Parce que vous pourriez être obligé d'ajouter de la pagination. Si vous avez paginé depuis le serveur, le filtre client sur commande, serait dans la page actuelle. Ce qui dérouterait l'utilisateur final. Donc, si vous avez un serveur, envoyez la commande avec l'appel et laissez le serveur le renvoyer.

Jens Alenius
la source
0

Conseil utile:

Vous pouvez inverser votre tableau avec vanilla Js: yourarray .reverse ()

Attention: l'inverse est destructif, il changera donc votre tableau, pas seulement la variable.

Ke Vin
la source
-2

Je dirais que l'utilisation de la méthode inverse native de tableau est toujours un meilleur choix que de créer un filtre ou de l'utiliser $index.

<div ng-repeat="friend in friends.reverse()">{{friend.name}}</div>

Plnkr_demo .

Vishnudas Tekale Kulkarni
la source
Vous inversez le tableau d'origine ... Une meilleure pratique serait de renvoyer un nouveau tableau qui est inversé.
Vandervidi