Angularjs orderBy работает неправильно

Я изменил пример, приведенный в документации angularjs. Я ставлю ноль для всех полей возраста в этом примере, и когда я нажимаю кнопку сортировки по возрасту, список сортируется (не знаю, на основе какого параметра сортируется список), хотя все поля возраста равны нулю и не должны быть отсортировано.

Планкер: https://plnkr.co/edit/85dmPRFu6IPhHnTkXqgU?p=preview

Просмотр:

<div ng-controller="ExampleController">
      <pre>Sort by = {{propertyName}}; reverse = {{reverse}}</pre>
      <hr />
      <button ng-click="propertyName = null; reverse = false">Set to unsorted</button>
      <hr />
      <table class="friends">
        <tbody>
          <tr>
            <th>
              <button ng-click="sortBy('name')">Name</button>
              <span class="sortorder" ng-show="propertyName === 'name'" ng-class="{reverse: reverse}"></span>
            </th>
            <th>
              <button ng-click="sortBy('phone')">Phone Number</button>
              <span class="sortorder" ng-show="propertyName === 'phone'" ng-class="{reverse: reverse}"></span>
            </th>
            <th>
              <button ng-click="sortBy('age')">Age</button>
              <span class="sortorder" ng-show="propertyName === 'age'" ng-class="{reverse: reverse}"></span>
            </th>
          </tr>
          <tr ng-repeat="friend in friends | orderBy:propertyName:reverse">
            <td>{{friend.name}}</td>
            <td>{{friend.phone}}</td>
            <td>{{friend.age}}</td>
          </tr>
        </tbody>
      </table>
    </div>

Контроллер:

.controller('ExampleController', ['$scope', function($scope) {
    var friends = [
      {name: 'John',   phone: '555-1212',  age: 0},
      {name: 'Mary',   phone: '555-9876',  age: 0},
      {name: 'Mike',   phone: '555-4321',  age: 0},
      {name: 'Adam',   phone: '555-5678',  age: 0},
      {name: 'Julie',  phone: '555-8765',  age: 0}
    ];

    $scope.propertyName = 'age';
    $scope.reverse = true;
    $scope.friends = friends;

    $scope.sortBy = function(propertyName) {
      $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;
      $scope.propertyName = propertyName;
    };
  }

person Sateesh Kumar Alli    schedule 23.11.2016    source источник
comment
Все поля возраста равны 0, поэтому он будет сортироваться в порядке заданного массива. И reverse будет обратным порядком данного массива   -  person simon    schedule 23.11.2016


Ответы (3)


Под капотом angularjs используется эта функция< /а>:

function doComparison(v1, v2) {
  for (var i = 0, ii = predicates.length; i < ii; i++) {
    var result = compare(v1.predicateValues[i], v2.predicateValues[i]);
    if (result) {
      return result * predicates[i].descending * descending;
    }
  }

  return compare(v1.tieBreaker, v2.tieBreaker) * descending;
}

Поскольку ваши v1 и v2 всегда одинаковы, compare(v1.tieBreaker, v2.tieBreaker) всегда будет возвращать одно и то же значение -1 (поскольку v1.value равно v2.value, используется tieBreaker), тогда как переменная descending будет либо -1, либо 1 в зависимости от порядка сортировки. Это то, что делает угловой порядок изменения.

Если бы вы не использовали sortOrder в этом фильтре:

friend in friends | orderBy:propertyName:reverse

или не менялись при каждом нажатии здесь:

$scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;

порядок не изменится.

person Max Koretskyi    schedule 23.11.2016
comment
Так есть ли способ изменить это поведение? - person Sateesh Kumar Alli; 23.11.2016
comment
Поскольку вы ничего не можете изменить в исходниках angular.js, вам нужно либо не изменять reverse, если propertyName всех значений массива равны, либо предоставить свой собственный компаратор sortBy - person Max Koretskyi; 23.11.2016
comment
Спасибо. Я добавил проверку перед изменением значения $scope.reverse. - person Sateesh Kumar Alli; 23.11.2016
comment
@SateeshKumarAlli, пожалуйста, тогда ты можешь принять мой ответ - person Max Koretskyi; 23.11.2016

Фактическая причина вашего вывода заключается в том, что когда вы нажимаете на возрастной фильтр, данные больше не будут сортироваться. Он показывает ваш $scope.friends в точном порядке, который сохранен в контроллере.

person Nitheesh    schedule 23.11.2016
comment
Он показывает точный порядок только при первом нажатии. Порядок меняется после первого клика. - person Sateesh Kumar Alli; 23.11.2016

Как предложил @Maximus, я добавил проверку перед переключением значения $scope.reverse на true или false.

$scope.sortBy = function(propertyName) {

      $scope.propertyName = propertyName;
     // check all the values of propertyName i.e. age in the array
     for (var i=0; i < friends.length; i++) {
        // toggle $scope.reverse only when the values are not same (zero in my case)
        if (friends[i].age !== 0) {
            $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;
        }
    }
    };

https://plnkr.co/edit/vMira2iF94yuOqJw3gA7?p=preview

person Sateesh Kumar Alli    schedule 23.11.2016
comment
Вы можете опубликовать это как отдельный вопрос? Вы можете получить больше информации по этой проблеме, чем только от меня. Я ответил на вопрос, почему так происходит. У меня может не хватить знаний, чтобы подсказать, как это исправить. - person Max Koretskyi; 23.11.2016
comment
вы можете связать вопрос здесь, когда вы его задаете - person Max Koretskyi; 23.11.2016