algolia / instantsearch

⚡️ Libraries for building performant and instant search and recommend experiences with Algolia. Compatible with JavaScript, TypeScript, React and Vue.
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/
MIT License
3.71k stars 522 forks source link

[refinementList]: sortBy does not correctly sort UTF8 chars #1377

Closed pixelastic closed 5 years ago

pixelastic commented 8 years ago

image

When using the the name sorting (or keeping the default one), facets starting with an accented character are put at the end.

Instead of the default sorting on strings, we could use localeCompare. It needs to know the user locale, but this is already an information we can pass to the main instance (to specify how to format numbers), so we could re-use it here as well.

It will require a change in the Helper as well I guess.

vvo commented 8 years ago

The helper uses lodash sortBy I believe. Do you know how to do it with lodash? Searched a bit without luck

pixelastic commented 8 years ago

Seems there is no way to pass a custom sort function to sortBy. What can be done though, is use a normalized string through _.deburr.

Something like

var facets = _.sortBy(facetValues, (facet) => { return _.deburr(facet.name) });

This will convert Éric to Eric before applying the sort. Not perfect, but closer to what we want to achieve here.

vvo commented 8 years ago

Ok so this looks like a helper improvement then. I wonder if we could make it the new default without breaking anything that people are expecting. But clearly your example shows that today at least for french names, doesn't make sense.

bobylito commented 8 years ago

@pixelastic, @vvo is right, that's probably something we can look at, but on the Helper side of things. Can you fill in your issue there?

pixelastic commented 8 years ago

Done.

Thanks :)

Haroenv commented 5 years ago

You can use the sortBy argument to pass a regular JS sort function to override the sorting behaviour.

search.addWidget(
  instantsearch.widgets.refinementList({
    container: '#brand-list',
    attributeName: 'brand',
    sortBy({ name: a }, { name: b }) {
      return a.localeCompare(b);
    },
  })
);

https://codesandbox.io/s/713rl3zwzq

Sorting can also be done in transformItems if you so prefer.