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

227

Как я могу получить обратный массив в угловых? я пытаюсь использовать фильтр 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>
Delremm
источник
4
Это новый и правильный способ stackoverflow.com/a/16261373/988830
om471987
@ QuiteNothing Это правильный путь, если вы хотите обратить массив с помощью выражения. В этом случае вопрос заключался в том, как почитать массив без такового.
JayQuerie.com
<tr ng-repeat = "друг в друзьях | orderBy: '- name'">
desmati
Смотрите мой ответ ниже для простой 1 строки и правильного решения. Там нет необходимости делать какие-либо методы. Интересно, почему люди делают для этого дополнительные методы.
Мухаммед
Всегда используйте фильтры для изменения ng-repeatповедения! @Trevor Senior проделал хорошую работу.
Амир Саванд

Ответы:

329

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

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

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

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

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


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

JayQuerie.com
источник
21
Ницца! Просто знайте, что items.reverse()модифицирует массив, а не просто создает новый и возвращает его.
Андерс Экдаль
12
Спасибо! Я упустил это из виду. Я добавил, slice()чтобы решить эту проблему.
JayQuerie.com
9
Вы должны добавить, if (!angular.isArray(items)) return false;чтобы убедиться, что у вас есть массив, прежде чем пытаться обратить его.
респект TheCode
6
Нужно быть более защищенным от нуля, вместо этого следует использовать следующее: возвращать предметы? items.slice (). reverse (): [];
Крис Юнг
5
@Chris Yeung: не рекомендуется возвращать пустое "[]", когда ноль. Лучше вернуть оригинальное значение.
Шива
202

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

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

Обновить:

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

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

или

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

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

Amit Bakle
источник
Уинг track by, это единственный способ, который работал для меня
@delboud вы должны использовать трек после orderBy:ng-repeat="friend in friends | orderBy:'+': true track by $index"
Vibhum Bhardwaj
125

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

Он упоминается в документации : «Если ни одно из свойств не предусмотрено (например , „+“) , то сам элемент массива используется для сравнения , где сортировки». Итак, решение будет:

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

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

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

Дмитрий Гончар
источник
1
Спасибо за чаевые! Как гласит кто-то другой, читающий это, похоже, что это не работает в rc4 ( v1.3.0-rc.4). Если у кого-нибудь появится шанс попробовать его в новом выпуске, сообщите нам!
mikermcneil
1
@mikermcneil Спасибо за комментарий! Согласно той же документации, он должен работать, начиная с v1.3.0-rc.5( rc.5 docs против rc.4 docs ). Я обновил ответ
Дмитрий Гончар
1
Не работает для меня (v1.3.5). Пробовал orderBy:'+':true, orderBy:'-':true, orderBy:'-':false, orderBy:'+':false:(
Cody
2
@ Коди Извините за поздний ответ. Вот, пожалуйста, рабочий пример с угловой версией v1.3.5 jsfiddle.net/dmitry_gonchar/L98foxhm/1 . Вероятно, проблема была в другом месте.
Дмитрий Гончар
1
@alevkon Правда. Но это работает, если вы укажете поле ('+ id', '-id' fe). Может быть, это ошибка в Angular, что она не работает с обычным порядком, если вы не укажете поле? Я взял этот метод из документации (ссылка в ответе), поэтому я был удивлен так же, как и вы. В любом случае, вопрос состоял в том, чтобы обратить массив.
Дмитрий Гончар
54

Вы можете повернуть по параметру $ index

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

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

ng-repeat = "friend in friends | orderBy: reverse:true"
Мухаммед Хассам
источник
2
Работает просто отлично для меня. Спасибо!
HankScorpio
17

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

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

Кумар
источник
11

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

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

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

Вишну
источник
1

При использовании MVC в .NET с Angular вы всегда можете использовать OrderByDecending () при выполнении вашего запроса БД следующим образом:

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

Тогда на угловой стороне, это будет уже полностью изменено в некоторых браузерах (IE). При поддержке Chrome и FF вам нужно будет добавить orderBy:

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

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

whyoz
источник
0

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

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

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

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

Например,

{"India":"IN","America":"US","United Kingdon":"UK"} json object
[{"country":"India","countryId":"IN"},{"country":"America","countryId":"US"},{"country":"United Kingdon","countryId":"UK"}] 
user5891403
источник
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;
};
}
Twois
источник
0

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

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

Йенс Алениус
источник
0

Полезный совет:

Вы можете перевернуть массив с помощью vanilla Js: yourarray .reverse ()

Внимание: реверс является разрушительным, поэтому он изменит ваш массив, а не только переменную.

Ке Вин
источник
-2

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

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

Plnkr_demo .

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