ng-repetir angular en reversa

227

¿Cómo puedo obtener una matriz invertida en angular? Estoy tratando de usar el filtro orderBy, pero necesita un predicado (por ejemplo, 'nombre') para ordenar:

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

¿Hay alguna manera de revertir la matriz original, sin ordenar? como eso:

<tr ng-repeat="friend in friends | orderBy:'':true">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
<tr>
Delremm
fuente
44
Esta es la forma nueva y correcta stackoverflow.com/a/16261373/988830
om471987
@QuiteNothing Esa es la forma correcta si desea invertir una matriz con una expresión. En este caso, la pregunta era cómo venerar una matriz sin una.
JayQuerie.com
<tr ng-repeat = "amigo en amigos | orderBy: '- name'">
desmati
Vea mi respuesta a continuación para la línea simple 1 y la solución correcta. No hay necesidad de hacer ningún método. Me pregunto por qué la gente está haciendo métodos adicionales para esto.
Muhammad Hassam
¡Utilice siempre filtros para cambiar el ng-repeatcomportamiento! @Trevor Senior hizo un buen trabajo.
Amir Savand

Respuestas:

329

Sugeriría usar un filtro personalizado como este:

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

Que luego se puede usar como:

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

Véalo trabajando aquí: Demostración de Plunker


Este filtro se puede personalizar para satisfacer sus necesidades como se ve. He proporcionado otros ejemplos en la demostración. Algunas opciones incluyen verificar que la variable es una matriz antes de realizar el reverso, o hacer que sea más indulgente para permitir la reversión de más cosas como cadenas.

JayQuerie.com
fuente
21
¡Agradable! Solo tenga en cuenta que items.reverse()modifica la matriz en lugar de simplemente crear una nueva y devolverla.
Anders Ekdahl
12
¡Gracias! Lo había pasado por alto. Lancé un slice()para resolver ese problema.
JayQuerie.com
99
Debe agregar if (!angular.isArray(items)) return false;para verificar que tiene una matriz antes de intentar revertirla.
respectTheCode
66
Necesita estar más a la defensiva contra nulo, debería usar lo siguiente en su lugar: ¿devolver artículos? items.slice (). reverse (): [];
Chris Yeung
55
@Chris Yeung: No es aconsejable devolver "[]" vacío cuando es nulo. Es mejor devolver el valor original.
Siva el
202

Esto es lo que usé:

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

Actualizar:

Mi respuesta estuvo bien para la versión antigua de Angular. Ahora, deberías estar usando

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

o

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

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

amit bakle
fuente
Uing track by, esta es la única forma que funcionó para mí
@delboud deberías usar la pista después del pedido Por:ng-repeat="friend in friends | orderBy:'+': true track by $index"
Vibhum Bhardwaj
125

Perdón por mencionar esto después de un año, pero hay una solución nueva y más fácil , que funciona para Angular v1.3.0-rc.5 y posteriores .

Se menciona en los documentos : "Si no se proporciona ninguna propiedad (por ejemplo, '+'), el elemento de matriz en sí se usa para comparar dónde se ordena". Entonces, la solución será:

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

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

Esta solución parece ser mejor porque no modifica una matriz y no requiere recursos computacionales adicionales (al menos en nuestro código). He leído todas las respuestas existentes y todavía prefiero esta a ellas.

Dmitry Gonchar
fuente
1
¡Gracias por el consejo! Como aviso para cualquiera que lea esto, parece que esto no funciona en rc4 ( v1.3.0-rc.4). Si alguien tiene la oportunidad de probarlo en la nueva versión, ¡háganoslo saber!
mikermcneil
1
@mikermcneil ¡Gracias por el comentario! De acuerdo con la misma documentación, debería funcionar a partir de v1.3.0-rc.5( rc.5 docs vs rc.4 docs ). He actualizado la respuesta
Dmitry Gonchar
1
No funciona para mí (v1.3.5). Intentado orderBy:'+':true, orderBy:'-':true, orderBy:'-':false, orderBy:'+':false:(
Cody
2
@Cody Perdón por la respuesta tardía. Aquí tienes: un ejemplo de trabajo con angular v1.3.5 jsfiddle.net/dmitry_gonchar/L98foxhm/1 . Probablemente el problema estaba en otro lugar.
Dmitry Gonchar
1
@alevkon Cierto. Pero funciona si especifica el campo ('+ id', '-id' fe). ¿Quizás es un error en Angular, que no funciona con el orden normal si no especifica un campo? Tomé este método de los documentos (el enlace está en la respuesta), así que me sorprendió tanto como a usted. De todos modos, la pregunta era cómo revertir una matriz.
Dmitry Gonchar
54

Puede revertir por el parámetro $ index

<tr ng-repeat="friend in friends | orderBy:'$index':true">
jjhrms
fuente
13
Debería funcionar, pero no funciona (probado con y sin comillas $index). Estoy en Angular 1.1.5.
Ingeniero
2
A mí me funcionó (aunque usaba una propiedad para ordenar en lugar de $ index) stackoverflow.com/questions/16261348/…
Certificaciones
44
No funciona con AngularJS 1.2.13. Modifiqué mi conjunto de objetos para agregar una identificación a cada objeto. La identificación es el índice del objeto dentro de la matriz. Entonces ng-repeat="friend in friends | orderBy:'id':true"funciona.
tanguy_k
51

Solución simple: - (no es necesario hacer ningún método)

ng-repeat = "friend in friends | orderBy: reverse:true"
Muhammad Hassam
fuente
2
Funciona bien para mí. ¡Gracias!
HankScorpio
17

Simplemente puede llamar a un método en su alcance para revertirlo, de esta manera:

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

Tenga en cuenta que $scope.reversecrea una copia de la matriz ya que Array.prototype.reversemodifica la matriz original.

Anders Ekdahl
fuente
13

si está utilizando 1.3.x, puede usar lo siguiente

{{ orderBy_expression | orderBy : expression : reverse}}

Ejemplo Listar libros por fecha de publicación en orden descendente

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

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

Kumar
fuente
11

Si está utilizando angularjs versión 1.4.4 y superior , una forma fácil de ordenar es utilizando el " índice de $ ".

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

ver demo

vishnu
fuente
1

Cuando use MVC en .NET con Angular, siempre puede usar OrderByDecending () al hacer su consulta de db de esta manera:

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

Luego, en el lado angular, ya se invertirá en algunos navegadores (IE). Cuando sea compatible con Chrome y FF, deberá agregar orderBy:

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

En este ejemplo, estaría ordenando en orden descendente en la propiedad .Id. Si está utilizando la paginación, esto se vuelve más complicado porque solo se ordenaría la primera página. Tendría que manejar esto a través de un archivo de filtro .js para su controlador, o de alguna otra manera.

whyoz
fuente
0

También puedes usar .reverse (). Es una función de matriz nativa.

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

Pian0_M4n
fuente
Su voto negativo solo puede significar una cosa: tiene más datos entrantes. Si {} o [] sigue recibiendo datos, se invertirá cada vez, obviamente. Es un nuevo resumen
Pian0_M4n
Advertencia para quien quiera usar esto: reverseinvierte la matriz en su lugar, no solo devuelve una copia invertida. Esto significa que cada vez que se evalúa esto, la matriz se invertirá.
jcaron
0

Eso es porque estás usando el objeto JSON. Cuando enfrente tales problemas, cambie su Objeto JSON a Objeto de matriz JSON.

Por ejemplo,

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

Encontré algo como esto, pero en lugar de matriz uso objetos.

Aquí está mi solución para los objetos:

Añadir 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 luego se puede usar como

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

Si necesita soporte de navegador antiguo, deberá definir la función de reducción (esto solo está disponible en 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
fuente
0

Yo mismo me había frustrado con este problema, por lo que modifiqué el filtro creado por @Trevor Senior cuando me encontraba con un problema con mi consola que decía que no podía usar el método inverso. También, quería mantener la integridad del objeto porque esto es lo que Angular está usando originalmente en una directiva ng-repeat. En este caso, utilicé la entrada de estúpido (clave) porque la consola se molestaría diciendo que hay duplicados y en mi caso necesitaba rastrear por $ index.

Filtrar:

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

Contenedor Codificado
fuente
0

Estoy agregando una respuesta que nadie mencionó. Intentaría hacer que el servidor lo haga si tienes uno. El filtrado del lado del cliente puede ser peligroso si el servidor devuelve muchos registros. Porque podría verse obligado a agregar paginación. Si tiene paginación del servidor, entonces el filtro del cliente en orden, estaría en la página actual. Lo que confundiría al usuario final. Entonces, si tiene un servidor, envíe el pedido junto con la llamada y deje que el servidor lo devuelva.

Jens Alenius
fuente
0

Consejo útil:

Puede invertir su matriz con vanilla Js: yourarray .reverse ()

Precaución: el reverso es destructivo, por lo que cambiará su matriz, no solo la variable.

Ke Vin
fuente
-2

Supongo que usar el método inverso nativo de matriz siempre es una mejor opción que crear un filtro o usarlo $index.

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

Plnkr_demo .

Vishnudas Tekale Kulkarni
fuente
Está invirtiendo la matriz original ... Una mejor práctica sería devolver una nueva matriz que se invierte.
Vandervidi