Saif Bechan
Saif Bechan

Reputation: 17121

Specific ORDER BY FIELD in ng-repeat

I have searched google, and found a lot of ways to sort in ng-repeat, but I did not find any information for my situation. I also don't have code to supply, I do not really know if it is possible.

This is the problem. I have an array of Items and all of the Items have a group. The groups that are available are ['rare', 'uncommon', 'common']. Now I use a ng-repeat, but they come all spread apart. I want to order them by, Rare first, Uncommon second, and Common as last. Secondly all the Items have a price, and within each rarity, I want them also to be ordered by price.

Now in this example, I can just order by group desc alphabetical, but in my other situations this will not work. I am really looking for a method to order by strings.

In MySQL this could be achieved by:

SELECT * FROM fruit ORDER BY FIELD(name, 'Banana', 'Apple') DESC, price DESC;

Upvotes: 0

Views: 3144

Answers (2)

Roman Koliada
Roman Koliada

Reputation: 5102

You can create your custom filter like this:

app.filter('sortByGroup&Price', function($filter) {
  return function(input) {
    var result = [];
    var rare = $filter('filter')(input, {group: 'rare'});
    result.push($filter('orderBy')(rare,'price');
    var uncommon = $filter('filter')(input, {group: 'uncommon'});
    result.push($filter('orderBy')(uncommon,'price');
    var common = $filter('filter')(input, {group: 'common'});
    result.push($filter('orderBy')(common,'price');
    return result;
  };
});

ng-repeat="item in Items | sortByGroup&Price "

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691943

Straight from the official documentation of orderBy:

expression

A predicate to be used by the comparator to determine the order of elements.

Can be one of:

function: Getter function. The result of this function will be sorted using the <, ===, > operator.

string: [...]

Array: An array of function or string predicates. The first predicate in the array is used for sorting, but when two items are equivalent, the next predicate is used.

(emphasis mine)

So, you first need a function that allows comparing your groups, with 'rare' coming first, then 'uncommon', then 'common':

var orderedGroups = ['rare', 'uncommon', 'common'];
$scope.groupComparator = function(item) {
    return orderedGroups.indexOf(item.group);
}

You don't need anything for the price, since it's a field of the item, and orderBy can simply take the field name. So you can just do now

ng-repeat="item in items | orderBy:[groupComparator, 'price']"
    

Upvotes: 2

Related Questions