Я пытаюсь использовать ng-repeat с синтаксисом стиля словаря и применять порядок к значению ключа.
(key, value) in something | orderBy:'key'
Кажется, OrderBy работает не так, как ожидалось
Пример здесь http://jsfiddle.net/mhXuW/
Я пытаюсь использовать ng-repeat с синтаксисом стиля словаря и применять порядок к значению ключа.
(key, value) in something | orderBy:'key'
Кажется, OrderBy работает не так, как ожидалось
Пример здесь http://jsfiddle.net/mhXuW/
Параметры orderBy должны соответствовать именам свойств в массиве объектов.
Ваши данные должны выглядеть примерно так:
$scope.list2 = [ { id:"2013-01-08T00:00:00", name:'Joe'},
{ id:"2013-01-09T00:00:00", name:'Sue'}];
Тогда будет работать такой фильтр:
<div ng-repeat="item in list2 | orderBy:'id':true">
Обратите внимание, что orderBy работает во всем массиве (something
в вашем примере кода выше) и возвращает отсортированный массив. orderBy ничего не знает о key
и value
.
это не реализовано. см. здесь:
https://github.com/angular/angular.js/issues/1286
EDIT (27 августа 2013 г.): эта проблема, похоже, сейчас решена.
Я создал специальный фильтр, чтобы сделать это возможным для списка выбора:
.filter('toDictionaryArray', function () {
return function (obj) {
if (!(obj instanceof Object)) return obj;
var arr = [];
for (var key in obj) {
arr.push({ key: key, value: obj[key] });
}
return arr;
}
})
список выбора ng-options затем читается следующим образом:
<select ng-options="kv.key as kv.value for kv in p.options | toDictionaryArray | orderBy:'value'"></select>
Как говорит akonsu, функция была запрошена здесь. Тем не менее, я все еще не мог заставить его работать с последней (1.3.0) бета-версией.
Там хороший обходной путь, похороненный в комментариях (обратите внимание, что для этого требуется underscore, и вам придется заменить ссылки на "ключ" на "значение. $key" в приведенном выше примере):
[Добавить фильтр]:
app.filter('toArray', function() { return function(obj) { if (!(obj instanceof Object)) return obj; return _.map(obj, function(val, key) { return Object.defineProperty(val, '$key', {__proto__: null, value: key}); }); }});
Пример разметки:
<div ng-repeat="val in object | toArray | orderBy:'priority' | filter:fieldSearch"> {{val.$key}} : {{val}} </div>
Потенциальные недостатки:
- Object.defineProperty не будет работать так, как в IE8 (если вы не ум, делающий $key перечислимым, тогда это легкое изменение).
- Если ваши значения свойств не являются объектами, вы не можете установить свойство $key и это не удается.
- Он не интегрируется непосредственно в orderBy или ngRepeat поэтому синтаксис отличается.
Здесь хорошая работа (angular-toArrayFilter):
.filter('toArray', function () {
return function (obj, addKey) {
if ( addKey === false ) {
return Object.keys(obj).map(function(key) {
return obj[key];
});
} else {
return Object.keys(obj).map(function (key) {
if(typeof obj[key] == 'object') return Object.defineProperty(obj[key], '$key', { enumerable: false, value: key});
});
}
};
});
Вместо использования orderby-фильтра, который поддерживает только массивы, а не объекты. Вы можете написать свой собственный фильтр, как я взял код от Justin Klemm http://justinklemm.com/angularjs-filter-ordering-objects-ngrepeat/ и добавил поддержку для задания нескольких полей заказа. Ниже приведен фильтр для фильтрации на основе свойств в значениях, но вы можете легко изменить его для фильтрации на основе ключа.
app.filter('orderObjectBy', function()
{
return function(items, fields, reverse)
{
var filtered = [];
angular.forEach(items, function(item)
{
filtered.push(item);
});
filtered.sort(function (a, b)
{
var result = 0;
for (var i = 0; i < fields.length; ++i)
{
if (a[fields[i]] > b[fields[i]])
{
result = 1;
break;
}
else if (a[fields[i]] < b[fields[i]])
{
result = -1;
break;
}
}
return result;
});
if (reverse)
{
filtered.reverse();
}
return filtered;
};
});
Затем внутри вашей веб-страницы html5 используйте ее так, чтобы статистика была картой/словарем с парами значений ключа.
<div class="row" ng-repeat="stat in statistics | orderObjectBy: 'NumTimesPartnered', 'NumTimesOpponent']:true">
<div class="col col-33">{{stat.Name}}</div>
<div class="col"><center>{{stat.NumTimesPartnered}}</center></div>
<div class="col"><center>{{stat.NumTimesOpponent}}</center></div>
</div>