кутове ng-повторення у зворотному напрямку


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>

4
Це новий і правильний шлях stackoverflow.com/a/16261373/988830
om471987

@QuiteNothing Це правильний шлях, якщо ви хочете змінити масив з виразом. У цьому випадку питання полягало у тому, як відновити масив без одного.
JayQuerie.com

<tr ng-repe = "друг у друзях | orderBy: '- ім'я'">
десмати

Дивіться мою відповідь нижче простий 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>

Дивіться, як це працює тут: Демонстрація Plunker


Цей фільтр можна налаштувати так, щоб він відповідав вашим потребам. Я наводив інші приклади в демонстрації. Деякі параметри включають перевірку, що змінна є масивом перед виконанням реверсу, або роблячи її більш м'якою, щоб дозволити реверсування більшої кількості речей, таких як рядки.


21
Приємно! Просто пам’ятайте, що items.reverse()модифікує масив замість того, щоб просто створити новий і повернути його.
Андерс Екдал

12
Дякую! Я це не помітив. Я кинувся slice()на вирішення цієї проблеми.
JayQuerie.com

9
Ви повинні додати, if (!angular.isArray(items)) return false;щоб перевірити, чи є у вас масив, перш ніж намагатися його змінити.
повагаTheCode

6
Потрібно бути більш захисним проти нуля, слід використовувати натомість наступне: повернути предмети? items.slice (). зворотний (): [];
Кріс Йен

5
@Chris Yeung: Не рекомендується повертати порожній "[]", коли null. Краще повернути початкове значення.
Сіва

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


Uing track by, це єдиний спосіб, який працював для мене

@delboud, ви повинні використовувати трек за замовленнямBy: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 vs rc.4 docs ). Я оновив відповідь
Дмитро Гончар

1
Не працює для мене (v1.3.5). Пробував orderBy:'+':true, orderBy:'-':true, orderBy:'-':false, orderBy:'+':false:(
Cody

2
@Cody Вибачте за пізню відповідь. Ось вам - робочий приклад з кутовим v1.3.5 jsfiddle.net/dmitry_gonchar/L98foxhm/1 . Напевно, проблема була в іншому місці.
Дмитро Гончар

1
@alevkon Правда. Але він працює, якщо вказати поле ('+ id', '-id' fe). Можливо, це помилка в Angular, що вона не працює в нормальному порядку, якщо ви не вказуєте поле? Я взяв цей метод у docs (посилання є у відповіді), тому я був здивований так само, як і ви. У всякому разі, питання полягало в тому, як повернути масив.
Дмитро Гончар

54

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

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

13
Має працювати, але ні (намагався з цитатами і без них $index). Я на Angular 1.1.5.
Інженер

2
Працювало для мене (хоча використовували властивість для сортування замість $ index), але stackoverflow.com/questions/16261348/…
Серти

4
Не працює з AngularJS 1.2.13. Я змінив масив об'єктів, щоб додати ідентифікатор до кожного об'єкта. Ідентифікатор, що є індексом об'єкта всередині масиву. Потім ng-repeat="friend in friends | orderBy:'id':true"працює.
tanguy_k


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



1

Під час використання MVC в .NET з Angular ви завжди можете використовувати OrderByDecending (), виконуючи свій db-запит таким чином:

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

Потім на кутовій стороні вона вже буде перевернута в деяких браузерах (IE). Підтримуючи Chrome та FF, вам потрібно буде додати orderBy:

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

У цьому прикладі ви б сортували у порядку зменшення за властивістю .Id. Якщо ви використовуєте підкачку, це ускладнюється, оскільки буде відсортовано лише першу сторінку. Вам потрібно буде обробити це за допомогою .js-фільтрувального файлу для вашого контролера чи іншим способом.


0

Ви також можете використовувати .reverse (). Це нативна функція масиву

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


Ваш голосування може означати лише одне: у вас більше даних, що надходять. Якщо {} або [] продовжує отримувати дані, вони, очевидно, будуть змінюватися щоразу. Це новий дайджест
Pian0_M4n

Попередження для того, хто хоче цим скористатися: reverseповертає масив на місце, він не просто повертає перевернуту копію. Це означає, що кожен раз, коли це оцінюється, масив буде перевернутий.
jcaron

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

Я знайшов щось подібне, але замість масиву я використовую об'єкти.

Ось моє рішення щодо об’єктів:

Додати спеціальний фільтр:

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

Я сам розчарувався з цією проблемою, і тому я змінив фільтр, який створив @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

Я додаю одну відповідь, яку ніхто не згадував. Я б спробував змусити сервер це зробити, якщо у вас є. Фільтрування клієнтів може бути небезпечним, якщо сервер повертає багато записів. Тому що вас можуть змусити додати підкачки. Якщо у вас є пейджинг з сервера, то фільтр клієнта за замовленням буде на поточній сторінці. Що б заплутало кінцевого користувача. Тож якщо у вас є сервер, відправте замовлення з викликом і нехай сервер поверне його.


0

Корисна порада:

Ви можете змінити масив ванілі Js: yourarray .reverse ()

Застереження: реверс є руйнівним, тому він змінить ваш масив, не тільки змінну.


-2

Я б сказав, що використання нативного методу зворотного масиву - це завжди кращий вибір щодо створення фільтра або використання $index.

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

Plnkr_demo .


Ви обертаєте початковий масив ... Кращою практикою було б повернення нового масиву, який перевернуто.
Вандервіді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.