Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember sortBy on property:desc is not the same as reverse

In Ember 2, I tried sortBy on an Enumerable.

The sortBy('something:asc') works correct. But sortBy('something:desc') is not the same as sortBy('something:asc').reverse(). ( Is it not desc?)

I tried to change something property to boolean or string or number. It seems only "string" type works with reverse.

like image 280
Hao Avatar asked Aug 31 '25 18:08

Hao


1 Answers

Actually, the Ember.Enumerable.sortBy method doesn't take any direction, as seen here, that's how Ember.computed.sort works, as seen in the docs example as well as when following internal calls to here.

This means that in your code "asc" doesn't work either. You're just getting the correct result by chance. Relevant github issue

Additionally, the reason only strings work as arguments to sortBy is because sortBy internally calls Ember.get on each element to extract a property by the name you provided, and property names are strings.

In other words, the signature for sortBy is sortBy(property) (docs)

The way sortBy determines the order of elements is by calling the compare method from ember-runtime which, unfortunately, is an internal operation and there's no API to affect it.

Here's how to do sort in both directions properly:

  • ascending: sortBy('something')
  • descending: sortBy('something').reverse() (unfortunately)

I believe this is intentional since Ember follows the convention over configuration paradigm, basically forcing you to favor usage of Ember.computed.sort, especially if performance is important.

sortingBy: ['something:desc'],
sortedCollection: Ember.computed.sort('collection', 'sortingBy')

Another workaround you could do is to convert the Enumerable to a regular JS array using the toArray method, sort it, and then overwrite the property with the newly sorted array:

const sortedDesc = this.get('something')
  .toArray() // convert the enumerable to a regular JS array
  .sort(/* your descending sort comparison function */);

this.set('something', sortedDesc);

And this will be faster (no need to reverse an array), but will be more memory intensive since it creates a new array (by calling toArray) each time you sort.

like image 154
nem035 Avatar answered Sep 02 '25 06:09

nem035