在AngularJS中,如何指定二级排序?

时间:2013-12-04 00:13:43

标签: javascript angularjs sorting

以下代码改编自AngularJS教程第4步(http://docs.angularjs.org/tutorial/step_04

我可以使用Array在controller.js代码中指定辅助排序。它在加载时效果很好。

我相信模板就是问题所在。我无法弄清楚如何设置Angular将为过滤器正确识别的数组。如上所述,主要和次要排序在负载上运行良好。但是,当您查看组合框时,它错误地有第三个选项,当您将Order By组合框更改为“Newest”时,生成的排序错误。

这是一个显示问题的JSfiddle(参见HTML的第8行和Javascript的第26行): http://jsfiddle.net/M6JLe/6/

如果您更愿意查看代码,请点击此处:

<!-- template -->
<div ng-app='phonecatApp'>
    <div ng-controller="PhoneListCtrl">
        Search: <input ng-model="query"><br />
        OrderProp: {{orderProp}}<br />
        Sort by: 
       <select ng-model="orderProp">
          <option value="name">Alphabetical</option>
          <option value="['age','name']">Newest</option>
       </select>

       <br />

       <ul class="phones">
          <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
            {{phone.name}}
            <p>{{phone.snippet}} ({{phone.age}})</p>
          </li>
       </ul>



// Javascript
    'use strict';

    /* Controllers */

    var phonecatApp = angular.module('phonecatApp', []);

    phonecatApp.controller('PhoneListCtrl', function($scope) {
      $scope.phones = [
        {'name': 'Nexus S',
         'snippet': 'Fast just got faster with Nexus S.',
         'age': 4},
        {'name': 'Motorola XOOM™ with Wi-Fi',
         'snippet': 'The Next, Next Generation tablet.',
         'age': 2},
        {'name': 'Motorola XOOM™',
         'snippet': 'The Next, Next Generation tablet.',
         'age': 3},
        {'name': 'Apple iPhone 5s',
         'snippet': 'Apple\'s newest smartphone',
         'age': 3},
        {'name': 'ABC Phone X',
         'snippet': 'Some text snippet',
         'age': 3}
      ];

      $scope.orderProp = ['age','name'];
    });

2 个答案:

答案 0 :(得分:3)

正如您已经意识到的那样,问题是选择选项是字符串,而您使用orderProp作为数组。一种方法可以使这项工作(不一定是最好的):

修改HTML:

<select ng-model="orderProp">
    <option value="name">Alphabetical</option>
    <option value="age,name">Newest</option>
</select>
<br />
<ul class="phones">
    <li ng-repeat="phone in phones | filter:query | orderBy:getOrder()">{{phone.name}}
        <p>{{phone.snippet}} ({{phone.age}})</p>
    </li>
</ul>

对您的控制器的修改:

$scope.orderProp = "age,name";
$scope.getOrder = function () {
    var tokens = $scope.orderProp.split(",");
    var order = [];
    tokens.forEach(function (token) {
        order.push(token.toString());
    });

    return order;
};

请参阅working example

答案 1 :(得分:1)

我通过使用AngularJS的OrderBy功能找到了解决方案。请参阅下面的JSFiddle:

http://jsfiddle.net/M6JLe/8/

基本上在模板中我删除了数组字段列表并使用字符串来表示我想要做的排序(见下文):

<select ng-model="orderProp">
      <option value="name">Alphabetical</option>
      <option value="age_name">Age then Name</option>
      <option value="age">Newest</option>
      <option value="-age">Oldest</option>
</select>

然后在ng-repeat上,我将过滤器OrderBy指向控制器中的自定义函数:

<ul class="phones">
    <li ng-repeat="phone in phones | filter:query | orderBy:customOrderBy">
        {{phone.name}}
        <p>{{phone.snippet}} ({{phone.age}})</p>
    </li>
</ul>

以下是控制器修改:

$scope.orderProp = 'age_name';
$scope.customOrderBy = function(phone) {
  switch($scope.orderProp) {
     case 'age_name':
         return (phone.age < 100 ? (phone.age < 10 ? '00' + phone.age : '0' + phone.age) : phone.age) + ' ' + phone.name;
         break;
     case 'age':
         return phone.age;
         break;
     case '-age':
         return -phone.age;
         break;
     default:
         return phone.name;
         break;
  }
};

有效。但是我不喜欢的一些事情是......

  1. 如果年龄小于999,它只会按年龄和名字排序.Blech!
  2. 与函数方法相对的数组方法更适合对多个字段进行排序并且效果很好,但是在模板的select / option html中将数组指定为字符串值似乎会使AngularJS绊倒。在我看来,除非有一种方法可以指定选择/选项值,AngularJS可以正确地解析数组,所以这只是有点破碎。可悲的是,我无法弄明白。
  3. 目前,我认为这个解决方案必须要做。