我正在使用AngularJs,并且在模板中对哈希对象的属性进行排序时遇到了问题 我的目标是:
function TestCtrl($scope){
$scope.week = {'MONDAY': ['manuel'], 'TUESDAY': [], 'WEDNESDAY': ['valerio'], 'THURSDAY': ['manuel', 'valerio'], 'FRIDAY': []}
}
现在,当我尝试在模板中打印这些值时:
<div ng-repeat="(day, names) in week">
<span>{{day}}</span>
<ul> <li ng-repeat="name in names">{{name}}</li> </ul>
</div>
打印天数的顺序不同:FRIDAY MONDAY THURSDAY TUESDAY WEDNESDAY
我尝试应用过滤器orderBy
,但我认为它不适用于对象,只适用于数组......
我如何订购?
答案 0 :(得分:20)
根据AngularJS docs(版本1.3.20):
您需要知道JavaScript规范没有定义 它将返回对象键的顺序。为了拥有一个 保证键的确定性顺序,Angular版本最多 并包括1.3 按字母顺序对键进行排序。
解决方法是使用一组键:
function TestCtrl($scope){
$scope.week = {
'MONDAY': ['manuel'], 'TUESDAY': [],
'WEDNESDAY': ['valerio'], 'THURSDAY': ['manuel', 'valerio'],
'FRIDAY': []}
$scope.weekDays = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"];
}
在视图中使用数组进行迭代:
<div ng-repeat="day in weekDays">
<span>{{day}}</span>
<ul> <li ng-repeat="name in week[day]">{{name}}</li> </ul>
</div>
从AngularJS版本1.4.6更新docs:
1.4版删除了字母排序。我们现在依赖订单 运行
for key in myObj
时浏览器返回。
答案 1 :(得分:6)
没有办法像这样订购哈希对象。不仅仅是角度,而是一般的javascript。
我会将哈希对象转换为对象数组,如下所示:
$scope.week = [{day: 'MONDAY', names: ['manuel']}, {day: 'TUESDAY', names: []} ...];
然后将视图更改为:
<div ng-repeat="day in week|orderBy:'day'">
<span>{{day.day}}</span>
<ul> <li ng-repeat="name in day.names">{{name}}</li> </ul>
</div>
答案 2 :(得分:3)
这是在Angular 1.4中修复的。如下面的官方Angular文档中所述:
1.4版删除了字母排序。我们现在依赖订单 运行
时由浏览器返回for key in myObj
答案 3 :(得分:3)
实际上有一个简单的解决方案...... 如果您从头开始在浏览器中创建对象,您的浏览器将知道订单;
,默认情况下不会对对象键进行排序 BUT示例:
// test-1
var data = {};
data['a'] = 10;
data['b'] = 5;
data['c'] = 2;
Object.keys(data); // ["a", "b", "c"]
// test-2
var data = {};
data['b'] = 5;
data['a'] = 10;
data['c'] = 2;
Object.keys(data); // ["b", "a", "c"]
如此简单......重新创建对象......或者使用这个简单的过滤器:
.filter('orderObject', function () {
return function (object, reverse) {
var keys = Object.keys(object || {}).sort();
if (reverse) keys.reverse();
for (var ordered = {}, i = 0; keys[i]; i++) {
ordered[keys[i]] = object[keys[i]];
}
return ordered;
}
})
常规对象的示例:
<!-- MARKUP : DEFAULT -->
<table>
<tr ng-repeat="(key, value) in data">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
<!-- RESULT : test-1 -->
<table>
<tr>
<td>a</td>
<td>10</td>
</tr>
<tr>
<td>b</td>
<td>5</td>
</tr>
<tr>
<td>c</td>
<td>2</td>
</tr>
</table>
<!-- RESULT : test-2 -->
<table>
<tr>
<td>b</td>
<td>5</td>
</tr>
<tr>
<td>a</td>
<td>10</td>
</tr>
<tr>
<td>c</td>
<td>2</td>
</tr>
</table>
已排序对象的示例:
<!-- MARKUP : with FILTER orderObject:<reverse?> -->
<table>
<tr ng-repeat="(key, value) in data | orderObject">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
<!-- RESULT : test-1 without reverse -->
<table>
<tr>
<td>a</td>
<td>10</td>
</tr>
<tr>
<td>b</td>
<td>5</td>
</tr>
<tr>
<td>c</td>
<td>2</td>
</tr>
</table>
<!-- RESULT : test-2 with reverse -->
<table>
<tr>
<td>c</td>
<td>2</td>
</tr>
<tr>
<td>b</td>
<td>5</td>
</tr>
<tr>
<td>a</td>
<td>10</td>
</tr>
</table>
答案 4 :(得分:1)
这个问题已经过时了,但我最终想出了一个答案,我认为这可能是对以前一些答案的改进。
不是简单地将对象转换为数组,而是创建一个为您执行此操作的角度过滤器,然后再ngRepeat
或ngOptions
。
举个例子:
angular.module('myproject')
.filter('objOrder', function () {
return function(object) {
var array = [];
angular.forEach(object, function (value, key) {
array.push({key: key, value: value});
});
return array;
};
});
然后,使用如下对象:
$scope.degrees: {
ASC: "Associate's",
BAS: "Bachelor's",
MAS: "Master's",
MD: "M.D.",
JD: "J.D.",
PHD: "Ph.D",
OTH: "Other"
}
我们可以像这样使用它:
<select
ng-model="myDegree"
required
ng-options="item.key as item.value for item in degrees | objOrder"
>
</select>
这样,您既不必创建新数组并污染$scope
,也不必返回并更改实际的degrees
对象,这可能会产生不必要的副作用。