I am working on a small demo AngularJS app for my students, but I keep running into trouble with an orderBy filter on an ng-repeat. I am retrieving JSON data via AJAX from a PHP script. The data gets loaded fine, it's just the ordering that doesn't work.
This is the part of the HTML page I'm concerned with:
<div ng-controller="MemberListController">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
<button ng-click="predicate=''">Set to unsorted</button>
<table class="table">
<thead>
<tr>
<th>
<button ng-click="order('gender')">Geslacht</button>
<span class="sortorder" ng-show="predicate === 'gender'" ng-class="{reverse:reverse}"></span>
</th>
<th>
<button ng-click="order('first_name')">Voornaam</button>
<span class="sortorder" ng-show="predicate === 'first_name'" ng-class="{reverse:reverse}"></span>
</th>
<th>
<button ng-click="order('last_name')">Achternaam</button>
<span class="sortorder" ng-show="predicate === 'last_name'" ng-class="{reverse:reverse}"></span>
</th>
<th>Geboren</th>
<th>Lid sinds</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="member in members track by member.id | orderBy:predicate:reverse" ng-hide="member.deleted == 1">
<td>{{ member.gender }}</td>
<td>{{ member.first_name }}</td>
<td>{{ member.last_name }}</td>
<td>{{ member.birth_date | date:'dd-MMM-yyyy' }}</td>
<td>{{ member.member_since | date:'dd-MMM-yyyy' }}</td>
</tr>
</tbody>
</table>
</div>
(function ()
{
// init the module
var app = angular.module('ledenjs', []);
// define the memberlist controller
app.controller('MemberListController', ['$scope', '$http', function ($scope, $http)
{
// define and set the scope properties
$scope.members = [];
$scope.predicate = 'last_name';
$scope.reverse = false;
// define the order method
$scope.order = function (predicate)
{
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
};
// read the members from the db
$http.get('MY_URL_HERE')
.success(function (response)
{
console.log('Received ' + response.length + ' members.');
$scope.members = response;
})
.error(function ()
{
alert('Could not retrieve members from server.');
});
}]);
})();
$result = mysqli_query($mysqli, "SELECT * FROM ledenjs");
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
header("Content-Type: application/json");
echo json_encode($data);
[{"id":"10001","birth_date":"1953-09-02","first_name":"Georgi","last_name":"Facello","gender":"M","member_since":"1986-06-26","deleted":"0"},{"id":"10002","birth_date":"1964-06-02","first_name":"Bezalel","last_name":"Simmel","gender":"F","member_since":"1985-11-21","deleted":"0"},{"id":"10003","birth_date":"1959-12-03","first_name":"Parto","last_name":"Bamford","gender":"M","member_since":"1986-08-28","deleted":"0"},{"id":"10004","birth_date":"1954-05-01","first_name":"Chirstian","last_name":"Koblick","gender":"M","member_since":"1986-12-01","deleted":"0"}]
<tr ng-repeat="member in members | orderBy:predicate:reverse track by member.id">
<tr ng-repeat="member in members track by member.id | orderBy:predicate:reverse" ng-hide="member.deleted == 1">
- this line may break in AngularJS prior to version 1.2; try to remove the
track by member.id
part and see if it works.
Update: the real solution for Angular v.1.2 and later is:
ng-repeat="member in members | orderBy:predicate:reverse track by member.id"
- tracking should come after orderBy clause.