ng-repetição angular em sentido inverso


227

Como posso obter uma matriz invertida em angular? Estou tentando usar o filtro orderBy, mas ele precisa de um predicado (por exemplo, 'nome') para classificar:

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

Existe uma maneira de reverter a matriz original, sem classificar. Curtiu isso:

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

4
Este é o novo e direita maneira stackoverflow.com/a/16261373/988830
om471987

@QuiteNothing É o caminho certo se você deseja reverter uma matriz com uma expressão. Nesse caso, a questão era como reverenciar uma matriz sem uma.
JayQuerie.com

<tr ng-repeat = "amigo em amigos | orderBy: '- name'">
desmati 21/09/16

Veja minha resposta abaixo para a linha 1 simples e a solução correta. Não há necessidade de fazer nenhum método. Eu me pergunto por que as pessoas estão criando métodos adicionais para isso.
Muhammad Hassam

Sempre use filtros para mudar o ng-repeatcomportamento! @ Trevor Senior fez um bom trabalho.
Amir Savand

Respostas:


329

Eu sugeriria usar um filtro personalizado como este:

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

Que pode ser usado como:

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

Veja-o aqui: Demonstração Plunker


Esse filtro pode ser personalizado para atender às suas necessidades, conforme necessário. Eu forneci outros exemplos na demonstração. Algumas opções incluem verificar se a variável é uma matriz antes de executar o inverso ou torná-la mais branda para permitir a reversão de mais coisas, como seqüências de caracteres.


21
Agradável! Esteja ciente de que items.reverse()modifica a matriz em vez de apenas criar uma nova e devolvê-la.
Anders Ekdahl

12
Obrigado! Eu tinha esquecido isso. Eu joguei um slice()para resolver esse problema.
JayQuerie.com

9
Você deve adicionar if (!angular.isArray(items)) return false;para verificar se possui uma matriz antes de tentar revertê-la.
RespectTheCode 23/07

6
Precisa ser mais defensivo contra o nulo; deve usar o seguinte: retornar itens? items.slice (). reverse (): [];
precisa

5
@ Chris Yeung: Não é aconselhável retornar vazio "[]" quando nulo. Melhor retornar o valor original.
Siva

202

Isto é o que eu usei:

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

Atualizar:

Minha resposta foi boa para a versão antiga do Angular. Agora você deveria estar usando

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

ou

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

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


Uing track by, esta a única maneira que funcionou para mim

@delboud você deve estar usando o controle por após orderBy:ng-repeat="friend in friends | orderBy:'+': true track by $index"
vibhum Bhardwaj

125

Desculpe por trazer isso à tona depois de um ano, mas há uma solução nova e mais fácil , que funciona para o Angular v1.3.0-rc.5 e posterior .

É mencionado nos documentos : "Se nenhuma propriedade for fornecida, (por exemplo, '+'), o próprio elemento da matriz será usado para comparar onde a classificação". Portanto, a solução será:

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

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

Essa solução parece ser melhor porque não modifica uma matriz e não requer recursos computacionais adicionais (pelo menos em nosso código). Eu li todas as respostas existentes e ainda prefiro essa a elas.


1
Obrigado pela dica! Como um aviso para quem está lendo isso, parece que isso não funciona no rc4 ( v1.3.0-rc.4). Se alguém tiver a chance de experimentá-lo no novo lançamento, informe-nos!
mikermcneil

1
@mikermcneil Obrigado pelo comentário! De acordo com a mesma documentação, ele deve funcionar a partir do v1.3.0-rc.5( rc.5 docs vs rc.4 docs ). Atualizei a resposta
Dmitry Gonchar

1
Não está funcionando para mim (v1.3.5). Tentou orderBy:'+':true, orderBy:'-':true, orderBy:'-':false, orderBy:'+':false:(
Cody

2
@ Cody Desculpe pela resposta tardia. Aqui está, um exemplo de trabalho com o angular v1.3.5 jsfiddle.net/dmitry_gonchar/L98foxhm/1 . Provavelmente o problema estava em outro lugar.
Dmitry Gonchar

1
@alevkon True. Mas funciona se você especificar o campo ('+ id', '-id' fe). Talvez seja um erro no Angular, que não funcione na ordem normal se você não especificar um campo? Peguei esse método nos documentos (o link está na resposta) e fiquei surpreso com você. Enfim, a questão era como reverter uma matriz.
Dmitry Gonchar

54

Você pode reverter pelo parâmetro $ index

<tr ng-repeat="friend in friends | orderBy:'$index':true">

13
Deve funcionar, mas não (tente com e sem aspas $index). Estou no Angular 1.1.5.
Engenheiro de

2
Trabalhou para mim (estava usando uma propriedade para classificação em vez de $ index) stackoverflow.com/questions/16261348/…
Certs

4
Não funciona com o AngularJS 1.2.13. Modifiquei minha matriz de objetos para adicionar um ID a cada objeto. O ID é o índice do objeto dentro da matriz. Então ng-repeat="friend in friends | orderBy:'id':true"funciona.
19414 Tandy_k

51

Solução simples: - (não é necessário fazer nenhum método)

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

2
Funciona muito bem para mim. Obrigado!
HankScorpio

17

Você pode simplesmente chamar um método no seu escopo para revertê-lo, assim:

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

Observe que o $scope.reversecria uma cópia da matriz, pois Array.prototype.reversemodifica a matriz original.


13

Se você estiver usando o 1.3.x, poderá usar o seguinte

{{ orderBy_expression | orderBy : expression : reverse}}

Exemplo Listar livros por data de publicação em ordem decrescente

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

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


11

Se você estiver usando o angularjs versão 1.4.4 e superior , uma maneira fácil de classificar é usar o " $ index ".

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

ver demonstração


1

Ao usar o MVC no .NET com Angular, você sempre pode usar OrderByDecending () ao fazer sua consulta db assim:

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

Em seguida, no lado angular, ele já será revertido em alguns navegadores (IE). Ao oferecer suporte ao Chrome e ao FF, você precisará adicionar orderBy:

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

Neste exemplo, você classificaria em ordem decrescente na propriedade .Id. Se você estiver usando paginação, isso ficará mais complicado, pois somente a primeira página será classificada. Você precisaria lidar com isso por meio de um arquivo de filtro .js para seu controlador ou de alguma outra maneira.


0

Você também pode usar .reverse (). É uma função de matriz nativa

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


Seu voto negativo pode significar apenas uma coisa: você tem mais dados recebidos. Se o {} ou [] continuar recebendo dados, eles serão revertidos a cada vez, obviamente. É um novo resumo
Pian0_M4n

Aviso para quem quiser usar isso: reverseinverte a matriz no lugar, ela não retorna apenas uma cópia invertida. Isso significa que toda vez que isso for avaliado, a matriz será revertida.
jcaron

0

Isso porque você está usando o objeto JSON. Quando você enfrentar esses problemas, altere seu objeto JSON para JSON Array Object.

Por exemplo,

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


0

Eu encontrei algo parecido com isto, mas em vez de matriz eu uso objetos.

Aqui está minha solução para objetos:

Adicione filtro personalizado:

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

Que pode ser usado como

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

Se você precisar de suporte antigo ao navegador, precisará definir a função de redução (disponível apenas no 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;
};
}

0

Eu mesmo fiquei frustrado com esse problema e, por isso, modifiquei o filtro criado pelo @Trevor Senior, pois estava com um problema no meu console dizendo que ele não podia usar o método reverso. Eu também queria manter a integridade do objeto, porque é isso que o Angular está usando originalmente em uma diretiva ng-repeat. Nesse caso, usei a entrada de stupid (key) porque o console fica chateado ao dizer que há duplicatas e, no meu caso, eu precisava rastrear por $ index.

Filtro:

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


0

Estou adicionando uma resposta que ninguém mencionou. Eu tentaria fazer o servidor fazê-lo, se você tiver um. A filtragem do lado do cliente pode ser perigosa se o servidor retornar muitos registros. Porque você pode ser forçado a adicionar paginação. Se você tiver paginação a partir do servidor, o filtro do cliente no pedido estará na página atual. O que confundiria o usuário final. Portanto, se você tiver um servidor, envie o pedido com a chamada e deixe o servidor devolvê-lo.


0

Dica útil:

Você pode inverter sua matriz com Js de baunilha: yourarray .reverse ()

Cuidado: o reverso é destrutivo, por isso mudará sua matriz, não apenas a variável.


-2

Eu sugeriria que usar o método reverso nativo da matriz é sempre uma melhor escolha do que criar filtro ou usar $index.

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

Plnkr_demo .


Você está revertendo a matriz original ... Uma prática melhor seria retornar uma nova matriz que é revertida.
Vandervidi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.