Sateesh Kumar Alli Sateesh Kumar Alli - 14 days ago 6
AngularJS Question

Angularjs orderBy is not working correctly

I have modified the example given in the angularjs docs. I put zero for all age fields in that example and when I click on the age sorting button the list is getting sorted (don't know on which parameter basis the list is getting sorted) although all the age fields are zero and should not be sorted.


Plunker: https://plnkr.co/edit/85dmPRFu6IPhHnTkXqgU?p=preview


View:

<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:

.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;
};
}

Answer

Under the hood angularjs uses this function:

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;
}

Since your v1 and v2 are always the same, compare(v1.tieBreaker, v2.tieBreaker) will always return the same value -1 (since v1.value is equal to v2.value a tieBreaker is used), whereas descending variable will be either -1 or 1 depending on sort order. This is what makes angular change order.

If you wouldn't use sortOrder in this filter:

friend in friends | orderBy:propertyName:reverse

or didn't change is on each click here:

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

the order wouldn't change.