Show all using instantsearch.js connectMenu

Hello,

I am using the connectMenu with instantsearch.js: https://community.algolia.com/instantsearch.js/v2/connectors/connectMenu.html

Here’s my code at the moment (taken from the above page):

// custom `renderFn` to render the custom Menu widget
function renderFn(MenuRenderingOptions, isFirstRendering) {
  if (isFirstRendering) {
    MenuRenderingOptions.widgetParams.containerNode
      .html('<select></select');

    MenuRenderingOptions.widgetParams.containerNode
      .find('select')
      .on('change', function(event) {
        MenuRenderingOptions.refine(event.target.value);
      });
  }

  var options = MenuRenderingOptions.items.map(function(item) {
    return item.isRefined
      ? '<option value="' + item.value + '" selected>' + item.label + '</option>'
      : '<option value="' + item.value + '">' + item.label + '</option>';
  });

  MenuRenderingOptions.widgetParams.containerNode
    .find('select')
    .html(options);
}

// connect `renderFn` to Menu logic
var customMenu = instantsearch.connectors.connectMenu(renderFn);

// mount widget on the page
search.addWidget(
  customMenu({
    containerNode: $('#custom-menu-container'),
    attributeName: 'categories',
    limit: 10,
  })
);

I’m desperately trying to add a “Show all” option to my select menu… The closest thing that I’ve found online is this closed GitHub issue (I don’t think this was ever implemented): https://github.com/algolia/instantsearch.js/issues/428

Can you guys help?

Thanks a lot,
Nicolas Spehler

Hello @nspehler,

The key here is to understand that MenuRenderingOptions.refine() function works like a toggle. If you call it with the same value twice there will be no refinement (= See all option).

The strategy here is to add an element into options[] at the beginning with the see all option and if there’s already a refined item to set this See All option value to the refined item value. So when the user will select “See all” option it will remove the current refined value of the menu.

And to simplify the things for you, here is a jsfiddle https://jsfiddle.net/z5eoh1ov/ with the custom behaviour you wanted implemented.

I hope this will help you :slight_smile: Feel free to ask anything else.

Cheers, Maxime.

1 Like

Thank you so much Maxime! This works like a charm! :grinning:

I’m happy I could help you :slight_smile:

Feel free to reach us back if you need any more help, have a good day!

Hello Maxime,

Sorry to re-open this thread after a few months!

Using the code you shared, how would I be able to transform data?

To give you some more context, I have dates inside my select menu (for example, “2017-01-01”, “2017-01-02”, etc.) and I’m looking to display them as “January 1, 2018”, "January 2, 2018, etc.) using some basic JavaScript.

Where would I be able to do this?

Thank you very much for your help,
Nicolas

Nevermind, I just solved this. :blush:

For anyone reading this, here’s how I transformed data inside my customMenu:

var options = MenuRenderingOptions.items.map(function(item) {
    // Using moment.js to manipulate date
    const myDate = moment(item.value, 'YYYY-MM-DD').toDate();
    item.label = moment(myDate).format("MMM. YYYY");
            
    return item.isRefined
    ? '<option value="' + item.value + '" selected>' + item.label + '</option>'
    : '<option value="' + item.value + '">' + item.label + '</option>';
});
1 Like