AngularJS сортировка по недвижимости
То, что я пытаюсь сделать, это отсортировать некоторые данные по свойству. Вот пример, который я должен работать, но это не так.
Часть HTML:
<div ng-app='myApp'>
<div ng-controller="controller">
<ul>
<li ng-repeat="(key, value) in testData | orderBy:'value.order'">
{{value.order}}. {{key}} -> {{value.name}}
</li>
</ul>
</div>
</div>
Часть JS:
var myApp = angular.module('myApp', []);
myApp.controller('controller', ['$scope', function ($scope) {
$scope.testData = {
C: {name:"CData", order: 1},
B: {name:"BData", order: 2},
A: {name:"AData", order: 3},
}
}]);
И результат:
- A → ADatali >
- B → BDatali >
- C → CDatali >
... что ИМХО должно выглядеть так:
- C → CDatali >
- B → BDatali >
- A → ADatali >
Я что-то пропустил (здесь готов JSFiddle экспериментировать)?
Ответы
Ответ 1
Фильтр с угловым фильтром AngularJS просто поддерживает массивы - никаких объектов. Поэтому вам нужно написать собственный небольшой фильтр, который сортирует для вас.
Или измените формат данных, с которыми вы работаете (если у вас есть влияние на это). Массив, содержащий объекты, сортируется по собственному фильтру orderBy.
Вот мой фильтр orderObjectBy для AngularJS:
app.filter('orderObjectBy', function(){
return function(input, attribute) {
if (!angular.isObject(input)) return input;
var array = [];
for(var objectKey in input) {
array.push(input[objectKey]);
}
array.sort(function(a, b){
a = parseInt(a[attribute]);
b = parseInt(b[attribute]);
return a - b;
});
return array;
}
});
Использование в вашем представлении:
<div class="item" ng-repeat="item in items | orderObjectBy:'position'">
//...
</div>
Объекту в этом примере нужен атрибут position, но вы можете использовать любой атрибут в объектах (содержащий целое число), только по определению в представлении.
Пример JSON:
{
"123": {"name": "Test B", "position": "2"},
"456": {"name": "Test A", "position": "1"}
}
Вот скрипка, которая показывает вам использование:
http://jsfiddle.net/4tkj8/1/
Ответ 2
Это довольно легко, просто сделайте это так
$scope.props = [{order:"1"},{order:"5"},{order:"2"}]
ng-repeat="prop in props | orderBy:'order'"
Ответ 3
Не забывайте, что parseInt() работает только для значений Integer. Для сортировки строковых значений вам необходимо поменять это:
array.sort(function(a, b){
a = parseInt(a[attribute]);
b = parseInt(b[attribute]);
return a - b;
});
с этим:
array.sort(function(a, b){
var alc = a[attribute].toLowerCase(),
blc = b[attribute].toLowerCase();
return alc > blc ? 1 : alc < blc ? -1 : 0;
});
Ответ 4
Как вы можете видеть в коде angular -JS (https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js) ng-repeat не работает с объектами. Вот хак с sortFunction.
http://jsfiddle.net/sunnycpp/qaK56/33/
<div ng-app='myApp'>
<div ng-controller="controller">
<ul>
<li ng-repeat="test in testData | orderBy:sortMe()">
Order = {{test.value.order}} -> Key={{test.key}} Name=:{{test.value.name}}
</li>
</ul>
</div>
</div>
myApp.controller('controller', ['$scope', function ($scope) {
var testData = {
a:{name:"CData", order: 2},
b:{name:"AData", order: 3},
c:{name:"BData", order: 1}
};
$scope.testData = _.map(testData, function(vValue, vKey) {
return { key:vKey, value:vValue };
}) ;
$scope.sortMe = function() {
return function(object) {
return object.value.order;
}
}
}]);
Ответ 5
согласно http://docs.angularjs.org/api/ng.filter:orderBy, orderBy сортирует массив.
В вашем случае вы передаете объект, поэтому вам придется реализовать свою собственную функцию сортировки.
или передать массив -
$scope.testData = {
C: {name:"CData", order: 1},
B: {name:"BData", order: 2},
A: {name:"AData", order: 3},
}
взгляните на http://jsfiddle.net/qaK56/
Ответ 6
Вы должны действительно улучшить свою структуру JSON, чтобы решить вашу проблему:
$scope.testData = [
{name:"CData", order: 1},
{name:"BData", order: 2},
{name:"AData", order: 3},
]
Тогда вы могли бы сделать
<li ng-repeat="test in testData | orderBy:order">...</li>
Проблема, я думаю, в том, что переменные (ключ, значение) недоступны для фильтра orderBy, и вы не должны хранить данные в своих ключах в любом случае
Ответ 7
Вот что я сделал, и он работает.
Я просто использовал стробированный объект.
$scope.thread = [
{
mostRecent:{text:'hello world',timeStamp:12345678 }
allMessages:[]
}
{MoreThreads...}
{etc....}
]
<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >
Если бы я хотел сортировать по тексту, я бы сделал
orderBy : 'mostRecent.text'
Ответ 8
Armin answer + строгая проверка для типов объектов и не angular ключей, таких как $resolve
app.filter('orderObjectBy', function(){
return function(input, attribute) {
if (!angular.isObject(input)) return input;
var array = [];
for(var objectKey in input) {
if (typeof(input[objectKey]) === "object" && objectKey.charAt(0) !== "$")
array.push(input[objectKey]);
}
array.sort(function(a, b){
a = parseInt(a[attribute]);
b = parseInt(b[attribute]);
return a - b;
});
return array;
}
})
Ответ 9
Ниже приведено упорядочение объектов с помощью ключа ИЛИ с помощью ключа внутри объекта.
В шаблоне вы можете сделать что-то вроде:
<li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someKey'">
Или даже:
<li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someObj.someKey'">
Фильтр:
app.filter('orderObjectsBy', function(){
return function(input, attribute) {
if (!angular.isObject(input)) return input;
// Filter out angular objects.
var array = [];
for(var objectKey in input) {
if (typeof(input[objectKey]) === "object" && objectKey.charAt(0) !== "$")
array.push(input[objectKey]);
}
var attributeChain = attribute.split(".");
array.sort(function(a, b){
for (var i=0; i < attributeChain.length; i++) {
a = (typeof(a) === "object") && a.hasOwnProperty( attributeChain[i]) ? a[attributeChain[i]] : 0;
b = (typeof(b) === "object") && b.hasOwnProperty( attributeChain[i]) ? b[attributeChain[i]] : 0;
}
return parseInt(a) - parseInt(b);
});
return array;
}
})
Ответ 10
Я добавлю обновленную версию фильтра, которая сможет поддерживать следующий синтаксис:
ng-repeat="(id, item) in $ctrl.modelData | orderObjectBy:'itemProperty.someOrder':'asc'
app.filter('orderObjectBy', function(){
function byString(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
}
return function(input, attribute, direction) {
if (!angular.isObject(input)) return input;
var array = [];
for(var objectKey in input) {
if (input.hasOwnProperty(objectKey)) {
array.push(input[objectKey]);
}
}
array.sort(function(a, b){
a = parseInt(byString(a, attribute));
b = parseInt(byString(b, attribute));
return direction == 'asc' ? a - b : b - a;
});
return array;
}
})
Спасибо Армину и Джейсону за их ответы в этой теме, а Алнитак в этой теме.