Choices-js/Choices

Custom sorter function for search results

TravisHardman opened this issue · 2 comments

Is your feature request related to a problem? Please describe.

I've been trying to implement sorting for search results, which led me down a bit of a rabbit hole. I saw in your docs that "sorter" was not supported while searching, so I tried to add sortFn to my config.fuseOptions. That sort function ran, but the results in Choices.js weren't sorted as it dictated.

Finally, after a bit of debugging, I discovered this like in the Choices.js codebase, which hard-codes a sort-by-score function whenever the user is searching.

var filter = this._isSearching ? utils_1.sortByScore : this.config.sorter

This code overrides anything that happens in the Fuse sortFn, so sortByScore ends up being the only way to sort while searching.

Describe the solution you'd like

I would like a way to have a custom sort function while searching. I could see it working a few different ways:

  • A config option for searchSorter, which takes a function and defaults to sortByScore, just like the existing sorter option.
  • A config option for shouldSortWhileSearching, which uses the existing sorter config function when the user is searching.
  • Just falling back on the Fuse sortFn from the fuseOptions if it's provided.

Describe alternatives you've considered

I haven't found a workaround yet, but I figured I'd drop in this feature request, since any workaround does seem like it'll be quite hacky.

For what it's worth, the workaround I found was to handle the "search" event, then re-render the choices. This at least works for a single-select, which is all I needed.

choices = new Choices(select_el, {
  searchable: true,
  shouldSort: true,
  sorter: (a,b) => {
    // My sorting function here
  },
};
 
select_el.addEventListener('search', (e) => {
  choices._isSearching = false;
  choices._renderChoices(); // Uses the "sorter" function above because _isSearching is false
});

Hope that helps anyone who gets to this point, but it's pretty hacky. I stand by the feature request :)

Xon commented

The call to sortByScore is required to use the fuse.js scores with the list of choices to render. I'll need to look into why a custom sortFn isn't applying as expected