Search code examples
javascriptalgolia

Sorting a Refinement List in Algolia Using Integers in Title as Integers, not Varchar


I have a set of values in an Algolia refinement list that are being displayed this way when I sortBy: ['name:asc']:

enter image description here

How might I get this to display in the expected format:

Grade 1
Grade 2
Grade 3
Grade 4
...
Grade 11
Grade 12

(Even better if I could get 'Kindergarten' first before all other values!)

Here is the code I have so far:

search.addWidget(
    instantsearch.widgets.menu({
        container: '#grade_menu',
        attribute: 'grades_JSON.long',
        sortBy: ['name:asc'],
        limit: 13,
        cssClasses: {
            showMore: 'btn-dark',
            count: 'tiny-text',
        },
        templates: {
            item: `
                <li class="nav-item pl-0 ml-0">
                <a class="nav-link" href="@{{slug}}">
                <span class="@{{cssClasses.label}}">@{{label}}</span>
                <span class="@{{cssClasses.count}}">
                @{{#helpers.formatNumber}}@{{count}}@{{/helpers.formatNumber}}
                </span>
                </a>
                </li>
            `,
        },
     })
);

Solution

  • In your widget options, sortBy can be given a function that behaves like Array.sort

    Which means you could have something like:

    function sortGrades(a, b) {
      if (a.name == "Kindergarten") {
        return -1;
      } else if (b.name == "Kindergarten") {
        return 1;
      } else {
        return Number(a.name.match(/[0-9]+/)[0]) - Number(b.name.match(/[0-9]+/)[0]);
      }
    }
    
    search.addWidget(
        instantsearch.widgets.menu({
            // ...
            sortBy: sortGrades,
            // ...
         })
    );
    
    

    "Kindergarten" will always be sorted first, while other values will be sorted depending on the number within the facet name.