#javascript #angularjs #angularjs-ng-repeat #angularjs-orderby
#javascript #angularjs #angularjs-ng-repeat #angularjs-orderby
Вопрос:
Есть ли способ отсортировать карту объектов 1: 1 в angular.js использование фильтров (или любого другого метода) в блоке ng-repeat?
У меня есть:
obj:{
a:3,
c:5,
d:1,
g:15
}
По сути, я хотел бы иметь возможность делать что-то вроде этого:
<div ng-repeat="item in obj | orderBy:'value'"> {{ item.value }}</div>
Я хотел бы иметь возможность сортировать это представление данных либо по ключу, либо по значению. Я знаю, что angular OrderBy будет сортировать только массивы, поэтому он не будет сортировать этот объект. Однако, если бы я мог превратить этот объект в массив объектов с ключом и значением в качестве свойств (предпочтительно с использованием фильтра с именем ‘toArray’):
var arr = [
{
key:'a',
value:'3'
},
{
key:'c',
value:5
},
....
]
тогда я мог бы использовать что-то вроде этого:
<div ng-repeat="item in obj | toArray | orderBy:'value'"> {{ item.value }}</div>
Однако любая попытка написать такой фильтр привела к достижению 10 итераций digest(). Ошибка прерывания!, поскольку она обновляет новый массив объектов на каждой итерации.
Каково наилучшее (или любое) решение для сортировки карты объектов 1: 1 без необходимости реструктуризации данных в контроллере?
Комментарии:
1. Пожалуйста, предоставьте код для вашего
toArray
фильтра, чтобы мы могли перейти оттуда. Удар в темноте: правильно лиtoArray
циклируется ваш дескриптор? Некоторые объекты AngularJS имеют циклы.
Ответ №1:
Попробуйте angular-underscore, который вводит функции подчеркивания в angular.js . Затем вы можете написать код, подобный:
<div ng-repeat="item in values(obj) | orderBy:identity"> {{ item }}</div>
чтобы получить только значения; или
<div ng-repeat="item in pairs(obj) | orderBy:last"> Key: {{ item[0] }}; Value: {{item[1]}}</div>
чтобы получить как ключи, так и значения.
Это действительно просто. Плунжер здесь: http://plnkr.co/edit/Zb4XpaQUXZ8nZJqR493b?p=preview
Комментарии:
1. это выглядит многообещающе, я вижу, что он упорядочивает список по значению от наименьшего к наибольшему значению. как бы вы изменили этот порядок ?… от наивысшего значения к наименьшему значению
2. @user1394625 просто добавьте
:reverse
параметр следующим образом:<div ng-repeat="item in values(obj) | orderBy:identity:true"> {{ item }}</div>
. Вы можете обратиться к AngularJS doc OrderBy для получения дополнительной информации.
Ответ №2:
Вы думали о том, чтобы просто создать массив изначально в вашем контроллере вот так?
$scope.items = [];
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
$scope.items.push({ key: key, value: obj[key] });
}
}
Затем повторить итерацию items
?
<div ng-repeat="item in items|orderBy:'value'">{{ item.value }}</div>
По крайней мере, тогда вы заполняете массив только один раз. Это может быть проблемой, если исходный объект поступает из запроса или чего-то еще, но я думаю, вы могли бы довольно легко заполнить обратный вызов указанного запроса.
Комментарии:
1. На данный момент это единственное решение, которое я have…to сделайте это в контроллере. Я надеялся, что есть способ сделать это в представлении. Таким образом структурирован не только один объект, поэтому мне пришлось бы запускать каждый объект через функцию в контроллере. Не прерыватель сделки, но он выглядит чище, просто проходя через фильтр в представлении.
2. вероятно, вы могли бы каким-то образом использовать это как фильтр или директиву, но это не очень хорошо для производительности. Я полагаю, что он будет продолжать оценивать его каждый раз при запуске наблюдателя, поэтому вы будете генерировать этот массив каждый раз . Может быть, просто создайте сервис, который вы вводите в свой контроллер, чтобы сделать это? (например, Utils.somehelper)