Директива ng-repeat сортирует данные при использовании (ключ, значение)
У меня есть код вроде этого с ng-repeat = "(ключ, значение) в данных".
В контроллере:
$scope.Dates = {"Today":"30",
"This Week":"42",
"This Month": "Oct",
"This Quarter" : "Bad",
"This Year" : 2013
}
и ng-repeat в качестве
<div ng-repeat="(key,value) in Dates">
{{key}} ==> {{value}}
</div>
Выход идет в отсортированном порядке как
This Month ==> Oct
This Quarter ==> Bad
This Week ==> 42
This Year ==> 2013
Today ==> 30
Как избавиться от этой сортировки (странно), поскольку я хочу, чтобы ключи использовались в коде. Я проверил группу google, но была скрипка для использования двух массивов, в которых хранилось значение ключа. http://jsfiddle.net/Saulzar/puhML/3/b. Не хочешь идти с таким подходом.
Ответы
Ответ 1
Это ограничение JavaScript не Angular.
Из Третий выпуск ECMAScript:
4.3.3 Объект является членом типа Object. Это неупорядоченная коллекция свойств, каждая из которых содержит примитив значение, объект или функцию. Функция, хранящаяся в свойстве объект называется методом.
Из Спецификация языка ECMAScript
Порядок [...] перечисления свойств [...] не указывается.
Angular явно сортирует ключи объектов, чтобы обеспечить по крайней мере какое-то постоянное поведение.
Обходной путь - это перебрать извлеченные ключи:
<div ng-repeat="key in keys(Dates)">
{{key}} ==> {{Dates[key]}}
</div>
$scope.keys = function(obj){
return obj? Object.keys(obj) : [];
}
$scope.Dates = {
"Today":"30",
"This Week":"42",
"This Month": "Oct",
"This Quarter" : "Bad",
"This Year" : 2013
};
Ответ 2
EDIT: Я подал ошибку, не стесняюсь +1
ECMAScript не указывает порядок, в котором ключи должны быть итерированы, однако все основные браузеры реализуют объекты как связанные хэш-карту (сохраняет порядок), и многие библиотеки js зависят от этого поведения, и поэтому мы привыкли к этому, и это вряд ли изменится.
Angular с другой стороны (это полностью неожиданно) сортирует его по алфавиту. Я сам проверял исходный код, он жестко закодирован, и было бы неплохо, если бы он был разрешен в один прекрасный день. В противном случае функция (k, v) in obj
полностью бесполезна.
Вы действительно ничего не можете сделать с этим, tricking angular, чтобы думать, что ваш результат - массив не полезен для чего угодно, потому что тогда вам понадобятся цифровые клавиши...
Если это нормально, вы можете определить getter для длины:
Object.defineProperty(yourResultObjectOrPrototype, 'length', {
get: function(){
return Object.keys(this).length;
}
})
В противном случае вам понадобится какой-то фильтр, который будет перебирать объект с помощью for(var k in obj)
и сохранять результат в массиве.
Ответ 3
На самом деле есть ответ:
он называется orderBy, а не sort:
https://docs.angularjs.org/api/ng/filter/orderBy
{{ orderBy_expression | orderBy : expression : reverse}}
<tr ng-repeat="friend in friends | orderBy:'-age'">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
Ваш список просто должен быть списком, и вам может понадобиться индекс, чтобы узнать порядок набора
$scope.Dates = [{index:1, "Today":"30"},
{index:2,"This Week":"42"},
{index:3,"This Month": "Oct"},
{index:4,"This Quarter" : "Bad"},
{index:5,"This Year" : 2013}]
а затем
<tr ng-repeat="(key, value) in Dates | orderBy:'index'">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
Ответ 4
Это исправлено с Angular 1.4.
Подробнее здесь:
Раньше порядок элементов при использовании ngRepeat для итерации по свойствам объекта гарантированно согласовывался путем сортировки ключей в алфавитном порядке.
Теперь порядок элементов зависит от браузера в зависимости от порядка, возвращаемого из итерации по объекту с помощью синтаксиса for key in obj
.
Кажется, что браузеры обычно следуют стратегии предоставления ключей в том порядке, в котором они были определены...
Ответ 5
Мне удалось сортировать Object of Strings по ключу в алфавитном порядке, как это, с помощью ng-repeat!
В моем контроллере:
$scope.build_config = {
build_path : "/x/eng/build",
arch : "x86",
variant : "debug",
run_method : "boot",
};
$scope.get_keys = function (obj) {
if (obj)
return Object.keys(obj);
};
В моем HTML:
<tr ng-repeat="key in get_keys(build_config) | orderBy:'toString()'">
<td> {{key}} </td>
<td> {{selected.build_config[key]}} </td>
</tr>
Ответ 6
Object.keys не резервирует заказ - FYI
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
//массив как объект со случайным упорядочением клавиш
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(an_obj)); // console: ['2', '7', '100']
Я преобразовываю его в массив объекта
$scope.Dates = [
{ id: "Today", value:"30" },
{ id: "This Week", value:"42" },
{ id: "This Month", value: "Oct" },
{ id: "This Quarter", value : "Bad" },
{ id: "This Year", value : 2013 }
];
<li ng-repeat="date in Dates">{{date.id}} -> {{date.value}}</li>
http://jsfiddle.net/2hqew68k/1/
Ответ 7
Ну, как объяснено в документации Angular для ngRepeat
https://docs.angularjs.org/api/ng/directive/ngRepeat#iterating-over-object-properties
при использовании его для итерации по свойствам объекта он не будет работать
Встроенные фильтры orderBy и фильтр не работают с объектами, и выдает ошибку, если используется с одним.
Лучшее решение в этом случае я считаю, что использует массивы вместо объекта и его свойств. Поэтому просто преобразуйте его в массив, итерации свойств вашего объекта и, например, нажатия на новый массив. В конце концов, я думаю, что это был бы естественный выбор для коллекции, а не для одного объекта со многими свойствами.