Instantsearch.js: Menu as a select field

Created on 24 Feb 2016  路  13Comments  路  Source: algolia/instantsearch.js

Is there any simple way to have the menu widget appear as a select field? Also to have the first option to be "All" that would remove the refinement?

Needs Investigation

All 13 comments

Hi, do you mean you would want the menu to have the form of a <select> element?

Exactly. But I also want to have the first and default item to be "All" where the refinement is removed.

@candypaint I must say you will have to implement this widget yourself using our:

This is basically the only tools we use to build custom widgets. If you have some coding experience this is feasible.

Let's say you want to build a menu on the "categories" attribute name:

1. getConfiguration

We want to inform the helper that we want to add a new attribute for faceting.

var selectCategories = {
  getConfiguration: function() {
    return {
      hierarchicalFacets: [{
        name: 'categories',
        attributes: ['categories']
      }]
    }
  }
};

2. init

We will bind the change event on the select and refine the value using the helper.

Here's the select html that you need to put in your page

<select id="select-categories"></select>

The the widget code you complete:

var selectCategories = {
  getConfiguration...,
  $selectCategories: document.querySelector('#select-categories'),
  this._refine: function(helper, changeEvent) {
    // this is where we refine the categories
    helper.toggleRefinement('categories', changeEvent.target.value);
    // now trigger a new search
    helper.search();
  },
  init: function(params) {
    this._refine = this._refine.bind(this, params.helper);
    // regular HTML/JS coding to create or bind to an existing select box change event
    this.$mySelect.addEventListener('change', this._refine);
  }
};

3. render

We are going to rebuild the select values at each new result set, be it an action on the select or a new query or an action on another widget.

var selectCategories = {
  getConfiguration...,
  $selectCategories...,
  this._refine...,
  init...,
  render: function(params) {
    var hasCategorySelected = params.helper.hasRefinements('categories');
    var all = {name: 'All', value: ''};
    if (!hasCategorySelected) {
      all.isRefined = true;
    }
    var results = [all];
    results = results.concat(params.results.getFacetValues('categories').data || []);
    var selectValues = results.map(function(result) {
      return '<option value="' + result.value + '"' + result.isRefined ? ' selected' : '' + '>' + result.name + '<option>';
    });
    this.$selectCategories.innerHTML = selectValues;
  }
};

4. addWidget

search.addWidget(selectCategories);
search.start(); // should already be present in your page

Conclusion

Some steps might not be accurate and the code might fail but that's the general idea. If you have any question, add it here.

Thanks. Got the idea.

I still think you should consider having it built in as a option. The long list of categories for refinement is not practical in most cases for mobile.

@candypaint That's a good idea. We are currently not focused enough on mobile indeed.

yes @vvo this would be very nice as a basic builtin for instantsearch.js. Would make Algolia instantsearch.js a lot more mobile friendly, which would of course help the bulk of our 1m+ monthly unique users.

See #1904, thanks for feedback

Super, thank you @vvo!

@vvo

Is there support for converting a numericRefinementList into a numericSelector or menuSelector?

For example, my widget options look like this:

    options: [
      {name: 'Any'},
      {start: (timeNow-86400), end: timeNow, name: 'Past 24 hours'},
      {start: (timeNow-592200), end: timeNow, name: 'Past Week'}
    ]

Hi @Brotakuu. Can you describe in more details what would you like to achieve?

@bobylito I'm looking for the same. Basically, we want to show numericRefinementList as a select instead of a list of radio buttons. Would be great if it was a mode.

@sjelfull you can use connectNumericRefinementList and make it into a select. I鈥檓 on my phone now but the example in the documentation is exactly that, but you just need to change the DOM tags.

That looks perfect - i'll take a look.

Was this page helpful?
0 / 5 - 0 ratings