ng-repeat指令在使用时对数据进行排序(键,值)

时间:2013-10-30 07:55:51

标签: angularjs

我有一个像这样的代码,在数据中使用ng-repeat =“(键,值)”。 在控制器中:

  $scope.Dates = {"Today":"30",
                  "This Week":"42",
                  "This Month": "Oct",
                  "This Quarter" : "Bad",
                  "This Year" : 2013
                                }

和ng-repeat指令为

<div ng-repeat="(key,value) in Dates">
{{key}} ==> {{value}}
</div>

输出按顺序排列为

This Month ==> Oct
This Quarter ==> Bad
This Week ==> 42 
This Year ==> 2013
Today ==> 30

如何摆脱这种排序(奇怪),因为我想要在代码中使用密钥..我检查了谷歌组,但有一个小提琴使用两个数组,其中一个存储键值。 http://jsfiddle.net/Saulzar/puhML/3/b。不想采用这种方法。

7 个答案:

答案 0 :(得分:65)

这是JavaScript而非Angular的限制。

来自ECMAScript Third Edition

  

4.3.3对象是Object类型的成员。 这是属性的无序集合,每个属性都包含一个基元   价值,对象或功能。存储在属性中的函数   对象称为方法。

来自ECMAScript Language Specification

  

枚举属性的顺序[...]   未指定

Angular sorts object keys explicitly,以便提供至少某种持久行为。

解决方法是迭代提取的密钥:

<div ng-repeat="key in keys(Dates)">
  {{key}} ==> {{Dates[key]}}
</div>
$scope.keys = function(obj){
  return obj? Object.keys(obj) : [];
}

$scope.Dates = {
  "Today":"30",
  "This Week":"42",
  "This Month": "Oct",
  "This Quarter" : "Bad",
  "This Year" : 2013
};

答案 1 :(得分:10)

编辑:I've filed a bug随意+1

ECMAScript没有指定应该迭代哪些键的顺序,但是所有主流浏览器都将对象实现为链接哈希映射(保留顺序),并且许多js库依赖于此行为,所以我们已经习惯了它并且它已经习惯了几乎没有改变。

另一方面,Angular(完全意外)按字母顺序排序。我自己检查了源代码,它在那里是硬编码的,如果它有一天得到解决将会很好。否则,(k, v) in obj功能完全无用

你真的无法做任何事情,欺骗角度认为你的结果是一个数组对任何事情都没用,因为你需要数字键然后......

如果可以,您可以定义getter的长度:

Object.defineProperty(yourResultObjectOrPrototype, 'length', {
  get: function(){
    return Object.keys(this).length;
  }
})

否则你需要某种过滤器,它将使用for(var k in obj)迭代对象并将结果存储在数组中。

答案 2 :(得分:7)

实际上有一个答案: 它被称为orderBy而不是排序:

https://docs.angularjs.org/api/ng/filter/orderBy

{{ orderBy_expression | orderBy : expression : reverse}}

<tr ng-repeat="friend in friends | orderBy:'-age'">
      <td>{{friend.name}}</td>
      <td>{{friend.phone}}</td>
      <td>{{friend.age}}</td>
    </tr>

您的列表只需要是一个列表,您可能需要一个索引来了解设置顺序

$scope.Dates = [{index:1, "Today":"30"},
                  {index:2,"This Week":"42"},
                  {index:3,"This Month": "Oct"},
                  {index:4,"This Quarter" : "Bad"},
                  {index:5,"This Year" : 2013}]

然后

<tr ng-repeat="(key, value) in Dates | orderBy:'index'">
          <td>{{key}}</td>
          <td>{{value}}</td>
         </tr>

答案 3 :(得分:6)

这是fixed as of Angular 1.4

查看详情here

  

以前,通过将键排序为字母顺序,使用ngRepeat迭代对象属性时的项目顺序保证一致。

     

现在,项目的顺序取决于浏览器,具体取决于使用for key in obj语法迭代对象返回的顺序。

     

似乎浏览器通常遵循按照定义键的顺序提供密钥的策略......

答案 4 :(得分:2)

我能够按字母顺序对字符串对象进行排序,使用ng-repeat!

在我的控制器中:

$scope.build_config = {
  build_path :  "/x/eng/build",
  arch : "x86",
  variant : "debug",
  run_method : "boot", 
};

$scope.get_keys = function (obj) {
  if (obj)
    return Object.keys(obj);
};

在我的HTML中:

<tr ng-repeat="key in get_keys(build_config) | orderBy:'toString()'">
      <td> {{key}} </td>
      <td> {{selected.build_config[key]}} </td>
</tr>

答案 5 :(得分:1)

Object.keys不保留订单 - FYI https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

//具有随机键排序的对象数组

var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(an_obj)); // console: ['2', '7', '100']

我将它转换为对象数组

$scope.Dates = [
        { id: "Today",      value:"30" },
        { id: "This Week",  value:"42" },
        { id: "This Month", value: "Oct" },
        { id: "This Quarter", value : "Bad" },
        { id: "This Year",  value : 2013 }
    ];

<li ng-repeat="date in Dates">{{date.id}} -> {{date.value}}</li>

http://jsfiddle.net/2hqew68k/1/

答案 6 :(得分:0)

嗯,正如Angular的ngRepeat文档

中所述

https://docs.angularjs.org/api/ng/directive/ngRepeat#iterating-over-object-properties

当使用它来迭代对象的属性时,它将不起作用

  

内置过滤器orderBy和filter不适用于对象,和   如果与一个一起使用将抛出错误。

在这种情况下,我认为最好的解决方案是使用数组而不是对象及其属性。因此,只需将其转换为数组,迭代对象的属性并推送到新数组即可。毕竟,我认为这将是集合的自然选择,而不是具有许多属性的单个对象。