【问题标题】:Angularjs orderBy in ng-repeat not working as expectedng-repeat 中的 Angularjs orderBy 无法按预期工作
【发布时间】:2015-05-29 17:55:58
【问题描述】:

我的模板中有以下 div:

<div ng-repeat="item in billing_history | orderBy:'-timestamp'">{{ item.date }}</div>

console.log(JSON.stringify($scope.billing_history)) 给了我以下信息:

{
  "May, 2015":{
     "date":"May, 2015",
     "timestamp":1432921230
  },
  "March, 2015":{
     "date":"March, 2015",
     "timestamp":1427846400
  },
  "February, 2015":{
     "date":"February, 2015",
     "timestamp":1425168000
  }
}

不管怎样,都是这样显示的:

February, 2015
March, 2015
May, 2015

我试过orderBy:'-timestamp'orderBy:'+timestamp'

我真的不确定为什么这不起作用。有没有人看到任何可能出错的地方?

【问题讨论】:

  • 它不是一个数组,但你拥有的是对象,我想它不会工作......
  • 关于我需要做什么才能让它工作的任何建议? @PSL
  • 是的,添加了一个带有演示的答案。检查一下...您需要将视图模型设置为数组。你觉得你能做到吗?
  • 是的,我会努力的。谢谢@PSL

标签: angularjs angularjs-orderby


【解决方案1】:

您不能将order-by 过滤器与对象文字一起使用(否则它不会按预期工作)。你所拥有的是一个对象文字,基本上没有特定的保证顺序键(以及它的值)。您需要将其转换为数组。

例子:

angular.module('app', []).run(function($rootScope) {
  $rootScope.billing_history = [{
    "date": "May, 2015",
    "timestamp": 1432921230
  }, {
    "date": "March, 2015",
    "timestamp": 1427846400
  }, {
    "date": "February, 2015",
    "timestamp": 1425168000
  }]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <p>Reverse order:
  <div ng-repeat="item in billing_history | orderBy:'-timestamp'">{{ item.date }}</div>
  <p>Correct order:
  <div ng-repeat="item in billing_history | orderBy:'timestamp'">{{ item.date }}</div>
</div>

过滤器是一种选择,但请注意,过滤器对性能的要求很高(它们在每个摘要周期运行多次以稳定,因此过滤器中的内容很重要),对于大型对象上的此类操作,它非常棘手。所以最好适当地设置视图模型或在控制器本身中转换格式。

【讨论】:

    【解决方案2】:

    orderBy 过滤器适用于数组,而您正在对象上使用它。把对象转成数组试试看。

    演示 http://plnkr.co/edit/4XtrJQaJ1itrVbb9bwE7?p=preview

    【讨论】:

    • 不变。我试过orderBy: timestamp : reverseorderBy: timestamp
    【解决方案3】:

    您可以像 Justin Klemm here 那样创建自己的自定义过滤器

    app.filter('orderObjectBy', function() {
      return function(items, field, reverse) {
        var filtered = [];
        angular.forEach(items, function(item) {
          filtered.push(item);
        });
        filtered.sort(function (a, b) {
          return (a[field] > b[field] ? 1 : -1);
        });
        if(reverse) filtered.reverse();
        return filtered;
      };
    });
    

    然后你的标记变成:

    <div ng-repeat="item in billing_history | orderObjectBy:'timestamp'">
      {{ item }}
    </div>
    

    或者

    <div ng-repeat="item in billing_history | orderObjectBy:'-timestamp'">
      {{ item }}
    </div>
    

    看到这个jsBin

    【讨论】:

    • 不错!!但是过滤器是性能密集型的,特别是对于像这样的操作,最好在控制器上进行转换,而不是在 DOM 上使用过滤器。此外,已经有一个内置的过滤器,因此无需真正重新发明它恕我直言......
    • 感谢汤姆的解决方法。但是让它们成为数组是一个快速的解决方法。
    猜你喜欢
    • 1970-01-01
    • 2013-10-23
    • 2013-05-03
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    相关资源
    最近更新 更多