Angular - 无法使 ng-repeat orderBy 工作

Posted

技术标签:

【中文标题】Angular - 无法使 ng-repeat orderBy 工作【英文标题】:Angular - Can't make ng-repeat orderBy work 【发布时间】:2013-10-23 15:08:43 【问题描述】:

我用 orderBy 尝试了很多 ng-repeat 的例子,但我无法让我的 json 使用它。

<div ng-app>
    <script type="text/javascript" src="http://code.angularjs.org/1.0.1/angular-1.0.1.js"></script>
    <div ng:controller="Main">
        <div ng-repeat="release in releases| orderBy:'environment_id'">      
            release.environment_id
        </div>
    </div>
</div>

还有 JSON

function Main($scope) 
$scope.releases = 
    "tvl-c-wbap001 + tvl-webapp": 
        "timestamp": " 05:05:53 PM ",
        "environment_id": "CERT5",
        "release_header": "Projects/Dev",
        "date": "19 Oct",
        "release": "12.11.91-1"
    ,
    "tvl-c-wbap401 + tvl-webapp": 
        "timestamp": " 10:07:25 AM ",
        "environment_id": "CERT4",
        "release_header": "Future Release",
        "date": "15 Oct",
        "release": "485-1"
    ,
    "tvl-c-wbap301 + tvl-webapp": 
        "timestamp": " 07:59:48 AM ",
        "environment_id": "CERT3",
        "release_header": "Next Release",
        "date": "15 Oct",
        "release": "485-1"
    ,
    "tvl-c-wbap201 + tvl-webapp": 
        "timestamp": " 03:34:07 AM ",
        "environment_id": "CERT2",
        "release_header": "Next Changes",
        "date": "15 Oct",
        "release": "13.12.3-1"
    ,
    "tvl-c-wbap101 + tvl-webapp": 
        "timestamp": " 12:44:23 AM ",
        "environment_id": "CERT1",
        "release_header": "Production Mirror",
        "date": "15 Oct",
        "release": "13.11.309-1"
    ,
    "tvl-s-wbap002 + tvl-webapp": 
        "timestamp": " 12:43:23 AM ",
        "environment_id": "Stage2",
        "date": "15 Oct",
        "release": "13.11.310-1"
    ,
    "tvl-s-wbap001 + tvl-webapp": 
        "timestamp": " 11:07:38 AM ",
        "environment_id": "Stage1",
        "release_header": "Production Mirror",
        "date": "11 Oct",
        "release": "13.11.310-1"
    ,
    "tvl-p-wbap001 + tvl-webapp": 
        "timestamp": " 11:39:25 PM ",
        "environment_id": "Production",
        "release_header": "Pilots",
        "date": "14 Oct",
        "release": "13.11.310-1"
    ,
    "tvl-p-wbap100 + tvl-webapp": 
        "timestamp": " 03:27:53 AM ",
        "environment_id": "Production",
        "release_header": "Non Pilots",
        "date": "11 Oct",
        "release": "13.11.309-1"
    

不管我写什么,我总是得到相同的订单,或者我可能会说,根本没有订单。

【问题讨论】:

【参考方案1】:

orderBy 仅适用于数组 -- 请参阅 http://docs.angularjs.org/api/ng.filter:orderBy

也是一个很好的过滤器,用于对象而不是数组@Angularjs OrderBy on ng-repeat doesn't work

【讨论】:

我有一个数组,但这在 Chrome 中不起作用。你知道为什么吗?【参考方案2】:

您将不得不将您的发布对象重新格式化为对象的数组。然后您就可以按照您尝试的方式对它们进行排序。

【讨论】:

【参考方案3】:

如前所述,只允许使用数组。但是为了简单起见,您可以通过管道函数将对象动态转换为数组,如此处所示 https://gist.github.com/brev/3949705

只需声明过滤器,并将其添加到 ng-repeat :)

<div ng-app="myApp">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<div ng-controller="Main">
  <div ng-repeat="release in releases | object2Array | orderBy:'environment_id'">release.environment_id</div>
</div>

<script>

var app = angular.module('myApp', []).filter('object2Array', function() 
    return function(input) 
      var out = []; 
      for(i in input)
        out.push(input[i]);
      
      return out;
    
  )
.controller('Main',function ($scope) 
        $scope.releases = "tvl-c-wbap001 + tvl-webapp":"timestamp":" 05:05:53 PM ","environment_id":"CERT5","release_header":"Projects/Dev","date":"19 Oct","release":"12.11.91-1","tvl-c-wbap401 + tvl-webapp":"timestamp":" 10:07:25 AM ","environment_id":"CERT4","release_header":"Future Release","date":"15 Oct","release":"485-1","tvl-c-wbap301 + tvl-webapp":"timestamp":" 07:59:48 AM ","environment_id":"CERT3","release_header":"Next Release","date":"15 Oct","release":"485-1","tvl-c-wbap201 + tvl-webapp":"timestamp":" 03:34:07 AM ","environment_id":"CERT2","release_header":"Next Changes","date":"15 Oct","release":"13.12.3-1","tvl-c-wbap101 + tvl-webapp":"timestamp":" 12:44:23 AM ","environment_id":"CERT1","release_header":"Production Mirror","date":"15 Oct","release":"13.11.309-1","tvl-s-wbap002 + tvl-webapp":"timestamp":" 12:43:23 AM ","environment_id":"Stage2","date":"15 Oct","release":"13.11.310-1","tvl-s-wbap001 + tvl-webapp":"timestamp":" 11:07:38 AM ","environment_id":"Stage1","release_header":"Production Mirror","date":"11 Oct","release":"13.11.310-1","tvl-p-wbap001 + tvl-webapp":"timestamp":" 11:39:25 PM ","environment_id":"Production","release_header":"Pilots","date":"14 Oct","release":"13.11.310-1","tvl-p-wbap100 + tvl-webapp":"timestamp":" 03:27:53 AM ","environment_id":"Production","release_header":"Non Pilots","date":"11 Oct","release":"13.11.309-1"
    );
</script>

【讨论】:

我使用更简单的toArray 过滤器:function(obj)return Object.keys(obj).map(function(key)return obj[key];); 太棒了……太棒了。感谢您发布此信息。大有帮助! 我不确定过滤器是否会发生这种情况,但是如果您使用函数在每个排序上创建一个数组,则 $digest 会多次触发。谁能告诉这是否也使用过滤器发生?见docs.angularjs.org/error/$rootScope/infdig 难道现在orderBy不仅支持数组吗? De doc 链接声明:“还支持类似数组的值(例如 NodeLists、jQuery 对象、TypedArrays、字符串等)。”【参考方案4】:

在上面 Eike Thies 的回复中,如果我们使用 underscore.js,过滤器可以简化为:

var app = angular.module('myApp', []).filter('object2Array', function() 
  return function(input) 
    return _.toArray(input);
  
);

【讨论】:

迄今为止最好的答案!太棒了。【参考方案5】:

迭代对象时,内置 orderBy 过滤器将不再起作用。由于对象字段的存储方式,它被忽略了。您需要创建一个自定义过滤器

yourApp.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;
  ;
);

<ul>
<li ng-repeat="item in items | orderObjectBy:'color':true"> item.color </li>
</ul>

【讨论】:

【参考方案6】:

这是@Julian Mosquera 的代码的一个版本,它也支持按对象key排序:

yourApp.filter('orderObjectBy', function () 
    return function (items, field, reverse) 
        // Build array
        var filtered = [];
        for (var key in items) 
            if (field === 'key')
                filtered.push(key);
            else
                filtered.push(items[key]);
        
        // Sort array
        filtered.sort(function (a, b) 
            if (field === 'key')
                return (a > b ? 1 : -1);
            else
                return (a[field] > b[field] ? 1 : -1);
        );
        // Reverse array
        if (reverse)
            filtered.reverse();
        return filtered;
    ;
);

【讨论】:

【参考方案7】:

orderby 适用于包含具有可用作过滤器的即时值的对象的数组,即

controller.images = [favs:1,name:"something",favs:0,name:"something else"];

当上述数组重复时,可以使用 | orderBy:'favs' 直接引用该值,或在前面使用减号以降序

<div class="timeline-image" ng-repeat="image in controller.images | orderBy:'-favs'">
    <img ng-src=" images.name "/>
</div>

【讨论】:

【参考方案8】:

这是@Julian Mosquera 的代码的一个版本,它还支持在主字段为空或未定义的情况下使用“后备”字段:

yourApp.filter('orderObjectBy', function() 
  return function(items, field, fallback, reverse) 
    var filtered = [];
    angular.forEach(items, function(item) 
      filtered.push(item);
    );
    filtered.sort(function (a, b) 
      var af = a[field];
      if(af === undefined || af === null)  af = a[fallback]; 

      var bf = b[field];
      if(bf === undefined || bf === null)  bf = b[fallback]; 

      return (af > bf ? 1 : -1);
    );
    if(reverse) filtered.reverse();
    return filtered;
  ;
);

【讨论】:

以上是关于Angular - 无法使 ng-repeat orderBy 工作的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 无法使用 ng-submit 获取选定的 ng-repeated 单选按钮

Angular 自定义指令在 ng-repeat 中使用 if 条件

ng-repeat无法正常工作

Angular JS ng-repeat 和模态对话框

Angular 5 ng-repeat 实现

Angular中的ng-repeat元素之间的差距