简体   繁体   English

如何基于AngularJS中的子结果集对结果排序

[英]How do I order results based on a child set of results in AngularJS

Given that I have the following object: 鉴于我有以下对象:

{
    "bands": [{
        "name": "The Wibbles",
        "formed": 1992,
        "albums": [{
            "name": "A New Wibble",
            "songs": [{
                "name": "Song One",
                "time": "3:12"
            }, {
                "name": "Song Two",
                "time": "2:34"
            }, {
                "name": "Song Three",
                "time": "2:21"
            }, {
                "name": "Song Four",
                "time": "3:44"
            }, {
                "name": "Song Five",
                "time": "3:54"
            }]
        }, {
            "name": "The Wibbles Strike Back",
            "songs": [{
                "name": "Song Six",
                "time": "8:12"
            }, {
                "name": "Song Seven",
                "time": "7:34"
            }, {
                "name": "I Killed a Girl",
                "time": "8:21"
            }, {
                "name": "Monkey Fighters",
                "time": "7:44"
            }, {
                "name": "Funkallica",
                "time": "9:54"
            }]
        }]
    }]
}

Using AngularJS (and potentially underscore.js), how would I order albums by the shortest track, total album length, or by the shortest average length of the albums tracks? 使用AngularJS(以及可能的underscore.js),如何按最短曲目,总专辑长度或最短平均曲目长度排序专辑?

If I was to then add another band, how would I order the bands themselves by these filters (shortest track / album length / average track length)? 如果要添加另一个乐队,我将如何通过这些过滤器(最短曲目/专辑长度/平均曲目长度)对乐队进行排序?

Sorting number strings is kind of a pain, but we can still tackle it. 对数字字符串进行排序有点麻烦,但我们仍然可以解决。 Here is an example given the following html: 这是给定以下html的示例:

<div ng-repeat="band in bands">
  <h1>{{ band.name }}</h1>
  <div ng-repeat="album in band.albums">
    <h2>{{ album.name }}</h2>
    <ul>
      <li ng-repeat="songs in album.songs">
        <h3>{{ song.name }}</h3>
        <em>{{ song.time }}</em>
      </li>
  </div>
</div>

Now, to order the albums by shortest track: 现在,以最短的顺序订购专辑:

<div ng-repeat="band in bands">
  <h1>{{ band.name }}</h1>
  <div ng-repeat="album in band.albums | orderBy:shortestTrackByAlbum">
    <h2>{{ album.name }}</h2>
    <ul>
      <li ng-repeat="song in album.songs">
        <h3>{{ song.name }}</h3>
        <em>{{ song.time }}</em>
      </li>
    </ul>
  </div>
</div>

As you can see, in order to perform a custom orderBy we need to pass the function (NOT the result of the function) on the current Scope that will be used to return the value that is being sorted; 如您所见,为了执行自定义orderBy我们需要在当前Scope上传递函数(而不是函数的结果),该函数将用于返回正在排序的值。 in this case `orderBy:shortestTrackByAlbum'. 在这种情况下,为“ orderBy:shortestTrackByAlbum”。

$scope.bands = [...];
$scope.shortestTrackByAlbum = function(album) {
  var times = [];
  for (var i = 0; i < album.songs.length; i++) {
    var minutesAndSeconds = album.songs[i].split(':'),
        m = parseInt(minutesAndSeconds[0], 10),
        s = parseInt(minutesAndSeconds[1], 10);
    times.push(m * 60 + s);
  }
  return Math.min.apply(null, times);
};

Given the data you provided, I converted your times to seconds to find out the smallest number of seconds among the tracks. 根据您提供的数据,我将您的时间转换为秒,以找出轨道中最小的秒数。 This smallest number is then compared with the other albums' smallest number to sort all of these smallest numbers (forgive the redundancy). 然后将此最小数字与其他专辑的最小数字进行比较,以对所有这些最小数字进行排序(请避免冗余)。

Using this pattern, you should be able to write a function for each type of situation. 使用这种模式,您应该能够为每种情况编写函数。 See this Plunker for a simple example. 有关简单示例,请参见此柱塞

In addition: if you want the user to be able to change the sorting you could implement something like the following: 另外:如果您希望用户能够更改排序,则可以实现以下内容:

<select ng-model="sortingMethod"
        ng-options="m.fn as m.name for m in methods"></select>

...
  <div ng-repeat="album in albums | orderBy:sortingMethod">
...
$scope.methods = [
  {
    name: 'Shortest Track',
    fn: $scope.shortestTrackByAlbum
  },
  {
    name: 'Total Album Length',
    fn: $scope.totalAlbumLengthByAlbum
  },
  {
    name: 'Shortest Average Length',
    fn: $scope.shortestAverageLengthByAlbum
  }
];

$scope.shortestTrackByAlbum = function(album) { ... };
$scope.totalAlbumLengthByAlbum = function(album) { ... };
$scope.shortestAverageLengthByAlbum = function(album) { ... };

Be sure and check out the docs on Angular Filters and more specifically Angular's OrderBy . 确保并查看有关Angular过滤器的文档,尤其是Angular的OrderBy

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM