如何在AngularJS中的ng-repeat指令中对对象数据源进行排序?

50

假设我有以下用户:

$scope.users = {
  "2": {
    email: 'john@gmail.com',
    name: 'John'
  },
  "3": {
    email: 'elisa@gmail.com',
    name: 'Elisa'
  }
}

我想创建一个带有以下选项的 <select>

<option value="3">Elisa</option>
<option value="2">John</option>

换句话说,用户应该按名称排序。

我尝试使用(key,value) in expression语法,但它不起作用:

<option ng-repeat="(user_id, user) in users | orderBy:'user.name'" 
        value="{{ user.id }}">
  {{ user.name }}
</option>

点击此处查看实际示例。

我错过了什么吗?

请勿建议使用 ng-options 的解决方案,因为我使用的是与 ng-options 不兼容的 ui-select2


我们不需要为这个问题添加两个新标签,只需要一个就够了。请帮助标签做个好事,添加一个适当的维基页面,并将它们添加到其他相关的问题中。如果你找不到其他与这些标签相关的问题,那么它们就没有必要重复存在了... - Charles
2
ng-repeatorderBy是AngularJS中非常常见的事情。我相信将会有更多关于这两个方面的问题。但无论如何,我已经将这些标签添加到其他一些问题中了。 - Misha Moroshko
由于我缺乏声望来正式建议标签备选拼写,这里的其他人应该添加angularjs-order-by。看起来很荒谬,驼峰式的ngRepeat会变成ng-repeat,而orderBy却变成了orderby - maurice
一个简单的例子:http://goo.gl/XYmwkr - Suresh Kamrushi
https://dev59.com/qGQo5IYBdhLWcg3wKsxr#58565750 - Abdo-Host
3个回答

56

虽然您可以在作者答案所引用链接的帖子中看到这一点,但我认为将其中提到的解决方法之一放在SO上会很好:

确实这个功能在技术上并没有被实现,但是如果您愿意轻微更改数据模型,有一个简单的解决方法:使用自定义过滤器生成对象属性的数组(不包括替换)。如果将键字段添加到对象中("id" 在上面的情况下),您应该能够获得您寻找的行为:

app.filter("toArray", function(){
    return function(obj) {
        var result = [];
        angular.forEach(obj, function(val, key) {
            result.push(val);
        });
        return result;
    };
});
...

$scope.users = {
    1: {name: "John", email: "john@gmail.com", id: 1},
    2: {name: "Elisa", email: "elisa@gmail.com", id: 2}
};

这里是可以使用的ng-repeat指令:

<option value="{{user.id}}" ng-repeat="user in users | toArray | orderBy:'name'">{{user.name}}</option>

这里是 plunkr

请注意,orderBy 过滤器以其参数 name 而不是 user.name 进行排序。

不幸的是,将 id 属性添加到您的对象中确实会创建潜在的键与包含对象中的键不匹配的可能性。

在您回答中提到的链接中,也提出了一些解决方案,可以即时为用户对象创建 id 属性,但我觉得这种方法有点不太整洁(代价是引入数据复制)。


@BarthZalewski 这看起来不错,但是如果我尝试反转过滤器,为什么什么都不会改变?你能处理像“reverse in cuh”这样的情况吗?ng-repeat="user in users | toArray | orderBy:'name' : reverse" - ak85
这种方法也适用于使用(key, value)在用户中的情况。干得好! - Robbie Smith
1
回应@ak85的问题,您可以使用ng-repeat="user in users | toArray | orderBy:'name' : true"来反转列表。布尔值true表示反向排序。 - Doug

9

9
值得一提的是,根据您引用的帖子,也没有计划实施它。 - mhess

0

补充采纳的答案并查看您的数据格式,您应将数据转换为

app.filter('myFilterUsers',function(){
    return function(data)
    {
        var newRes = [];
        angular.forEach(data,function(val,key){
            val["id"] = key;  //Add the ID in the JSON object as you need this as well.
            newRes.push(val);
        });
        return newRes;
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接