I have an array of objects i.e. filtered and paged and now I would like to order the list items by different object attributes.
I tried the orderBy
filter as follows:
<th><a href='' ng-click="reverse = sortParam == 'title' && !reverse; sortParam = 'title'">Title</a></th>
<tr ng-repeat="item in pagedItems|filter:filterParam|orderBy:sortParam:reverse">
<td>{{ item.title }}</td>
</tr>
This seems to be working fine, clicking on the Title
link, orders the row alphabetically or reverse alphabetically depending on the current state.
But the problem here is that only the pagedItems
are being ordered, which makes sense as we are applying the orderBy
filter to the pagedItems
. What I want to achieve is to order the whole set of items (not just currently paged items) to be ordered when the filter is applied.
In order to achieve this I thought i'd use a method in the controller scope. so I changed the above to:
/** In the Template */
<th><a href='' ng-click="sortItems('title')">Title</a></th>
<tr ng-repeat="item in pagedItems|filter:filterParam">
<td>{{ item.title }}</td>
</tr>
/** In the Controller */
$scope.sortItems = function(value) {
$scope.filtered = $filter('orderBy')($scope.filtered, value);
};
$scope.$watch('currentPage + numPerPage + filtered', function() {
$scope.pagedItems = getPagedItems($scope, 'filtered');
});
The sortItems
method works and changes the order but the items in the view does not get updated as the $watch
code is not fired. I assumed that maybe it's not being changed because the data in the $scope.filtered
is not being altered and just the indexes are being changed. So I added and empty element at the end of the array:
$scope.sortItems = function(value) {
$scope.filtered = $filter('orderBy')($scope.filtered, value);
$scope.filtered.push({});
};
Now, Everything works as expected but I can't keep an empty object in the array as it affects the items, count and data being displayed. So I thought I'd add and remove an empty item. So changed the above to :
$scope.sortItems = function(value) {
$scope.filtered = $filter('orderBy')($scope.filtered, value);
$scope.filtered.push({});
$scope.filtered.pop();
};
But guess what the $watch
code not being fired again.
Question
My question is does $watch
look for changes in an array based on it's length ? If yes, what is the best possible way to achieve what I'm trying to. Any help would be appreciated.
Ok I solved this using $broadcast
and $on
as follows:
$scope.sortList = function(value) {
if (value === $scope.currentFilter) {
value = value.indexOf('-') === 0 ? value.replace("-","") : "-" + value;
}
$scope.currentFilter = value;
$scope.filtered = $filter('orderBy')($scope.filtered, value);
$scope.$broadcast('sorted');
}
$scope.$on('sorted', function() {
$scope.pagedCandidates = getPagedItems($scope, 'filtered');
})