AngularJs在ngRepeat中排序对象

时间:2013-08-08 11:18:50

标签: angularjs angularjs-ng-repeat

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

我如何订购?

5 个答案:

答案 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

时由浏览器返回

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

答案 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)

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

不是简单地将对象转换为数组,而是创建一个为您执行此操作的角度过滤器,然后再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>

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