14

我正在使用 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,但我认为它不适用于对象,而仅适用于数组......

我该如何订购?

4

5 回答 5

21

根据 AngularJS文档(版本 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文档更新:

1.4 版删除了字母排序。我们现在依赖浏览器在运行时返回的顺序for key in myObj

于 2013-08-08T11:27:26.323 回答
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>
于 2013-08-08T11:28:35.033 回答
3

这已在 Angular 1.4 中修复。正如下面的官方 Angular 文档中所述:

1.4 版删除了字母排序。我们现在依赖浏览器在运行时返回的顺序for key in myObj

https://docs.angularjs.org/api/ng/directive/ngRepeat

于 2015-03-21T21:09:31.120 回答
3

实际上有一个简单的解决方案......默认情况下对象键没有排序但是如果您从头开始在浏览器中创建对象,您的浏览器知道顺序;)

例子:

// 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>
于 2016-02-17T09:09:40.360 回答
1

这个问题很老,但我最终想出了一个答案,我认为这可能是对以前的一些答案的改进。

与其简单地将对象转换为数组,不如创建一个角度过滤器来为您完成此操作,然后ngRepeatngOptions在此之上。

举个例子:

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>

这样,您既不必创建一个新数组和 pollute $scope,也不必返回并更改您的实际degrees对象,这可能会产生不必要的副作用。

于 2014-09-22T15:41:59.997 回答