algolia/instantsearch: connectMenu refine() remove current refined value

808 views Asked by At

Is there any way to REMOVE a refined value with connectMenu’s connector?

These are the things I tried that did not work:

  • passing an empty string refine('')
  • passing a null value refine(null)
  • passing a false value refine(false)
  • passing no parameter refine()

The reason why I’d like to do this is because otherwise currentRefinedValues widget shows an attribute as refined even if it’s not.

var customMenuRenderFn = function (renderParams, isFirstRendering) {
    var container          = renderParams.widgetParams.containerNode;
    var title              = renderParams.widgetParams.title || 'dropdownMenu';
    var templates          = renderParams.widgetParams.templates;
    var hideIfIsUnselected = renderParams.widgetParams.hideIfIsUnselected || false;
    var cssClasses         = renderParams.widgetParams.cssClasses || "";

    if (isFirstRendering)
    {
        $(container).append(
            (templates.header || '<h1>' + renderParams.widgetParams.attributeName + '</h1>') +
            '<select class="' + cssClasses.select + '">' +
                '<option value="__EMPTY__">Tutto</option>' +
            '</select>'
        ).hide();

        var refine = renderParams.refine;

        if (! hideIfIsUnselected)
        {
            $(container).show();
        }
        else
        {
            $(hideIfIsUnselected).find('select').on('items:loaded', function () {
                if (isFirstRendering) {
                    var valueToCheck = $(hideIfIsUnselected).find('select').val();

                    $(container).toggle(valueToCheck !== '__EMPTY__');

                    $(container).find('select').off('items:loaded');
                }
            });

            $(hideIfIsUnselected).find('select').on('change', function (event) {
                var value = event.target.value === '__EMPTY__' ? '' : event.target.value;

                if (value === '') {
                    refine();
                }

                $(container).toggle(value !== '');
            });
        }

        $(container).find('select').on('change', function (event) {
            var value = event.target.value === '__EMPTY__' ? '' : event.target.value;

            refine(value);
        });
    }

    function updateHits (hits)
    {
        var items  = renderParams.items;

        optionsHtml = ['<option class="' + cssClasses.item + '" value="__EMPTY__" selected>Tutto</option>']
            .concat(
                items.map(function (item) {
                    return `<option class="${cssClasses.item}" value="${item.value}" ${item.isRefined ? 'selected' : ''}>
                                ${item.label} (${item.count})
                            </option>`;
                })
            );

        $(container).find('select').html(optionsHtml);

        $(container).find('select').trigger('items:loaded');
    }

    if (hideIfIsUnselected && $(hideIfIsUnselected).val() !== '__EMPTY__') {
        updateHits(renderParams.items);
    } else if (! hideIfIsUnselected) {
        updateHits(renderParams.items);
    }
}

var dropdownMenu = instantsearch.connectors.connectMenu(customMenuRenderFn);
1

There are 1 answers

2
bobylito On BEST ANSWER

The refine function actually toggles the value (setting it if not set, or unsetting if set). If you want to unselect any item in the menu, you need to find the currently selected value and use refine on it.

connectMenu(function render(params, isFirstRendering) {
  var items = params.items;
  var currentlySelectedItem = items.find(function isSelected(i) {
    return i.isRefined;
  });
  params.refine(currentlySelectedItem);
});

This example won't solve your code completely, but it shows how to find the currently selected item and unselect it.