угловое повторение в обратном направлении

212

Как я могу получить обратный массив в angular? Я пытаюсь использовать фильтр orderBy, но для сортировки нужен предикат (например, "имя" ):

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

Есть ли способ отменить исходный массив без сортировки. например:

<tr ng-repeat="friend in friends | orderBy:'':true">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
<tr>
  • 4
    Это новый и правильный способ stackoverflow.com/a/16261373/988830
  • 0
    @ QuiteNothing Это правильный путь, если вы хотите перевернуть массив с помощью выражения. В этом случае вопрос заключался в том, как почитать массив без такового.
Показать ещё 3 комментария
Теги:
arrays
angularjs-ng-repeat
reverse

16 ответов

293
Лучший ответ

Я бы предложил использовать настраиваемый фильтр, например:

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

Что можно затем использовать как:

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

Посмотрите, как он работает здесь: демонстрация плунжера


Этот фильтр можно настроить так, чтобы он соответствовал вашим потребностям. Я привел другие примеры в демонстрации. Некоторые параметры включают проверку того, что переменная представляет собой массив перед выполнением обратного, или сделать его более мягким, чтобы разрешить изменение большего количества вещей, таких как строки.

  • 20
    Ницца! Просто items.reverse() что items.reverse() изменяет массив, а не просто создает новый и возвращает его.
  • 12
    Спасибо! Я упустил это из виду. Я добавил slice() чтобы решить эту проблему.
Показать ещё 7 комментариев
171

Это то, что я использовал:

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

Update:

Мой ответ был в порядке для старой версии Angular. Теперь вы должны использовать

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

или

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

из https://stackoverflow.com/questions/15266671/angular-ng-repeat-in-reverse

  • 0
    Uing track by , это единственный способ , который работал для меня
  • 0
    @delboud вы должны использовать track by after orderBy: ng-repeat="friend in friends | orderBy:'+': true track by $index"
106

Извините за то, что вы это сделали через год, но есть новое, более простое решение, которое работает для Angular v1.3.0-rc.5 и более поздних.

В docs указано: "Если свойство не предоставлено (например," + "), то сам элемент массива используется для сравнения, где сортировка". Таким образом, решение будет:

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

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

Это решение кажется лучше, потому что не модифицирует массив и не требует дополнительных вычислительных ресурсов (по крайней мере, в нашем коде). Я прочитал все существующие ответы и по-прежнему предпочитаю их для них.

  • 1
    Спасибо за чаевые! Как замечание для всех, кто читает это, похоже, что это не работает в rc4 ( v1.3.0-rc.4 ). Если у кого-нибудь появится шанс попробовать его в новом выпуске, дайте нам знать!
  • 1
    @mikermcneil Спасибо за комментарий! В соответствии с той же документацией, он должен работать начиная с v1.3.0-rc.5 ( rc.5 docs против rc.4 docs ). Я обновил ответ
Показать ещё 7 комментариев
43

Вы можете изменить параметр $index

<tr ng-repeat="friend in friends | orderBy:'$index':true">
  • 13
    Должно работать, но не работает (пробовал с и без кавычек вокруг $index ). Я на Angular 1.1.5.
  • 2
    Работал для меня (хотя вместо $ index использовали свойство для сортировки) stackoverflow.com/questions/16261348/…
Показать ещё 4 комментария
26

Простое решение: - (не нужно делать какие-либо методы)

ng-repeat = "friend in friends | orderBy: reverse:true"
  • 0
    не работает
  • 0
    Нету. Не работает
Показать ещё 3 комментария
15

Вы можете просто вызвать метод в своей области, чтобы отменить его для вас, например:

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

Обратите внимание, что $scope.reverse создает копию массива, так как Array.prototype.reverse изменяет исходный массив.

13

если вы используете 1.3.x, вы можете использовать следующие

{{ orderBy_expression | orderBy : expression : reverse}}

Пример Список книг по опубликованной дате в порядке убывания

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

источник: https://docs.angularjs.org/api/ng/filter/orderBy

  • 1
    orderBy : '-publishedDate' также работает.
9

Если вы используете angularjs версии 1.4.4 и выше, простой способ сортировки использует " $index".

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

посмотреть демо

1

При использовании MVC в .NET с Angular вы всегда можете использовать OrderByDecending() при выполнении своего db-запроса, например:

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

Затем на стороне Angular в некоторых браузерах (IE) он будет отменен. При поддержке Chrome и FF вам необходимо добавить orderBy:

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

В этом примере вы будете сортировать в порядке убывания свойства .Id. Если вы используете пейджинг, это становится более сложным, потому что будет отсортирована только первая страница. Вам нужно будет обработать это через файл фильтра .js для вашего контроллера или каким-либо другим способом.

0

Я добавляю один ответ, о котором никто не упоминал. Я постараюсь сделать сервер, если он у вас есть. Фильтрация клиентов может быть опасной, если сервер возвращает много записей. Потому что вы можете добавить пейджинг. Если у вас есть пейджинг с сервера, тогда клиентский фильтр по заказу будет находиться на текущей странице. Это путало бы конечного пользователя. Поэтому, если у вас есть сервер, отправьте заказ с вызовом и позвольте серверу вернуть его.

0

Я сам расстроился из-за этой проблемы, поэтому я изменил фильтр, созданный @Trevor Senior, когда у меня возникла проблема с моей консолью, говоря, что он не может использовать обратный метод. Я также хотел сохранить целостность объекта, потому что это то, что изначально использует Angular в директиве ng-repeat. В этом случае я использовал вход глупых (ключ), потому что консоль будет расстроена, говоря, что есть дубликаты, и в моем случае мне нужно было отслеживать по $index.

Фильтр:

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

Я нашел что-то вроде этого, но вместо массива я использую объекты.

Вот мое решение для объектов:

Добавить пользовательский фильтр:

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

который затем можно использовать как

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

Если вам нужна поддержка старого браузера, вам нужно будет определить функцию сокращения (это доступно только в 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

Фильтр orderBy выполняет стабильную сортировку с Angular 1.4.5. (См. Запрос на подачу GitHub https://github.com/angular/angular.js/pull/12408.)

Таким образом, достаточно использовать постоянный предикат, а reverse - true:

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

Это потому, что вы используете JSON Object. Когда вы сталкиваетесь с такими проблемами, измените объект JSON на объект массива JSON.

Например,

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

Вы также можете использовать .reverse(). Это встроенная функция массива

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

  • 0
    Ваш отрицательный голос может означать только одно: у вас есть больше входящих данных. Если {} или [] продолжают получать данные, они, конечно, будут возвращаться каждый раз. Это новый дайджест
  • 0
    Предупреждение для тех, кто хочет использовать это: reverse обращение массива на месте, оно не просто возвращает обратную копию. Это означает, что каждый раз, когда это оценивается, массив будет инвертирован.
-3

Я бы зарекомендовал себя, используя встроенный обратный метод, всегда лучший выбор по созданию фильтра или с помощью $index.

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

Plnkr_demo.

  • 0
    Вы переворачиваете исходный массив ... Лучше было бы вернуть новый массив, который перевернут.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню