rangeInput widget: Best way to mimic default min/max

Hey friends - I’m integrating a range input widget in my vanilla JS v3 InstantSearch app and am trying to figure out the best way to mimic the default min/max UX.

The goal: Allow a user to enter anything in the rangeInput fields, and do so while showing no currentRefinements for an empty initial search.

As far as I can tell, when using the default min/max (e.g. nothing entered in the rangeInput widget settings), there is no refinement, and thus, nothing appears in currentRefinements and the UI remains clean. The widget receives the min/max from the initial call and creates the html input min/max attributes from there.

The problem I’m having is the nature of my index causes the default min/max provided by the Algolia engine to be unusable (more on this below). If I enter a min/max in the rangeInput widget settings to override the defaults, that approach causes a refinement, creating an addition to the currentRefinements widget. It’s this last part I’m trying to overcome, e.g. allow a user to basically enter anything in the rangeInput widget, without showing any currentRefinements on the initial search.

Here’s a repro of the root issue (i.e. unusable default min/max) using the default InstantSearch CodeSandbox but with the additions of rangeInput and currentRefinements widgets (still using default latency index).

The Algolia engine provides a min/max of 14/100. But say I’m a college student with a $2,000 budget for a new laptop. I can’t enter 2000 as the max in the rangeInput widget as it’s limited by the HTML max attribute of 100.

So fine. I add new defaults for min/max in the rangeInput widget using the min and max options. Let’s say, 1 and 9999 to be generous. Now the currentRefinement widget shows an entry even on an empty initial search. From a UX standpoint, this seems confusing as the visitor has not yet added any refinements.

Here are all the solutions I’ve explored:

  1. Use min/max defaults in rangeInput settings
  • Issue: Unable to enter a max over 100 (the value provided by the Algolia engine) as per repro
  1. Set min/max in rangeInput widget settings
  • Issue: Results in currentRefinement
  1. Override html input min/max attribute in search.once event via removeAttribute/setAttribute/etc (included in repro but commented out)
  • Issue: Doesn’t actually refine the search unless value is w/in original range (e.g. 14 min 100 max)
  1. Exclude price from currentRefinement widget via the excludedAttributes option
  • Works, but degrades UX for when range input IS used (e.g. won’t show a refinement when a visitor DOES refine by price)
  1. Set min/max in rangeInput widget settings, but clear the initial currentRefinement in a custom routing function
  • Issue: Seems like a hack?

Perhaps I need to use the connector to create a fully custom rangeInput widget, but this feels like I’m missing something simple, so any and all suggestions are most welcome!

Hi Chad,

On empty queries (no query nor filters, which is you case), the engine optimizes the search by looking at the pre-computed best documents. It’s a list of 1000 documents that are best ranked according to the custom ranking. The facets counts are retrieved from this subset only. The reason behind this design choice is that computing facet counts is an expensive computation process. Doing it with an empty query would mean doing it on the whole index.

We are working on this current performance-related limitation right now. Unfortunately, I can’t give you any ETA at the moment.

As a workaround, you can set a default configuration to prevent the widget from computing the min and max values on a subset of the index using these parameters:

You can then exclude those default values from the currentRefinement widget using currentRefinements | InstantSearch.js | Algolia :

    container: '#range-input',
    attribute: 'price',
    min: 1,
    max: 9999,

    container: '#current-refinements',
    transformItems(items) {
      return items.filter(item => {
        const isDefaultRefinement = item.attribute === 'price' && item.refinements[0].value === 1 && item.refinements[1].value === 9999;
        return !isDefaultRefinement

I hope it helps,
Best regards.

Ah yes, transformItems, good call!

My initial exploration shows this option gets me a little closer, but may have some unintended consequences (e.g. result count seems to become an estimation, instead of the actual number). I’ll keep playing and will post any useful solutions I come up with.

And thanks so much for the fast and super informative response. It may simply be that I’ll have to use one of the other numeric/range options or come up with something custom. My UX roadblock is my index contains an abnormally wide range of numbers, so it will be hard to squeeze the necessary fidelity into the rangeSlider or numericMenu widgets.

For a little background on my specific use case, each of the 5m items in my index represents a grant made to a nonprofit by an institutional donor. These range from large negative amounts to just over a billion $'s, with the highest concentration in the $1-100 range. Though the most plentiful, these small grants are the least useful from a search perspective. For example, a typical search will involve a non-profit fundraiser search for grant comps that fit their typical grant profile, be it $2k-$10k, $5m-$12m, $250m-$750m, etc. It’s a huge and varied range.

I think all I really need are the overall index min/max amounts as defaults. From an engine perspective, I suppose they could be pulled at index time (relatively cheap), instead of at query time (expensive)?

BTW - I’ve updated the Codesandbox example with a short-lived test key should anyone want to play with my actual index and help brainstorm solutions. Algolians - lmk if you want full access to the source index data for test purposes if it helps the internal discussions. The 5m item index is fully open-source and comprised solely of public data. :raised_hands:

In case it helps others, turns out using the rangeInput connector resolved my issue (i.e. fully ignoring default min/max w/out showing currentRefinements).

The root cause of my particular issue was my ranking settings was throwing off the default min/max provided by the engine. I have the following ranking formula:

  1. Sort-By: tax_year (a number based category)
  2. Textual - all default ranking criteria/no changes
  3. Custom ranking: amount

It appears the engine was providing a min/max based solely on the Sort-By criteria, ignoring the custom ranking (i.e. the min/max represented the actual min/max for the latest tax year, NOT the overall index).

I know there’s been talk about supporting Infinity for min/max, and it appears this would have resolved my issue, just FYI. If the engine provided the overall index min/max, that would have also resolved the issue.

Project is fully open source, so here’s the live production site and source code.