Hello,
How can I make a custom widget that uses a <select> and can handle multiple values?
I have a custom widget that works with just 1 value and I now wanted to convert it into an widget that can handle multiple selections.
My current code:
instantsearch.widgets.customSelectorWidgetMultiple = function customSelectorWidgetMultiple(
options
) {
var container = options.container;
var attributeName = options.attributeName;
var limit = options.limit || 10;
var title = options.title || 'All';
var heading = options.heading;
// container should be a CSS selector, so we convert it into a DOM element
container = document.querySelector(container);
// We'll internally keep track of the <select> element
var selectElement = null;
// We'll also need to keep track of the current selected value
var currentlySelectedValue = [];
return {
// Method called at startup, to configure the Algolia settings
getConfiguration: function getConfiguration() {
// This is a copy-paste of the menu widget
// We use a hierarchicalFacet and not a classical facet because we want to
// keep the list of all possible values displayed at all times. With
// a classical facet we would only have the list of possible values for
// the current filters (which would not make any sense here)
return {
hierarchicalFacets: [
{
name: attributeName,
attributes: [attributeName],
},
],
};
},
// Called on the first instantsearch search
init: function init(options) {
var helper = options.helper;
var tooltip = '';
if ($(container).attr('data-tooltip'))
tooltip = getTemplate($(container).attr('data-tooltip'));
// We add an (empty) <select> to the specified container
container.innerHTML =
'<div class="ais-header selectWidget"><label for="' +
attributeName +
'-select">' +
heading +
tooltip +
'</label></div><div class="ais-body"><select id="' +
attributeName +
'-select" multiple data-maxOptions="1000"></select></div>';
selectElement = container.querySelector('select');
// We listen to the change event on that <select>
selectElement.addEventListener('change', function() {
// Finding the newly selected value
var $selectElement = $(selectElement);
helper.clearRefinements(attributeName);
if (
Array.isArray($selectElement.val()) &&
$selectElement.val().length > 0
) {
$selectElement.val().forEach(function(model) {
console.log('SET: ' + attributeName + ' ' + model);
helper.addDisjunctiveFacetRefinement(attributeName, model);
});
}
helper.search();
});
$('#' + attributeName + '-select').selectpicker({
liveSearch: true,
noneSelectedText: 'Alles',
});
},
// Called whenever we receive new results from Algolia
render: function render(options) {
var results = options.results;
// We get the list of possible values for this search and sort them in the
// same order everytime (most popular first)
var sortBy = ['name:asc'];
var facetValues = results.getFacetValues(attributeName, {
sortBy: sortBy,
}).data;
var innerOptions = ['<option value="__EMPTY__">' + title + '</option>'];
if (facetValues != null) {
$(container).show();
// We only keep the X first elements, as defined on instanciation
facetValues = facetValues.slice(0, limit);
// Then we add that to the <select>
facetValues.forEach(function(facetValue) {
// We mark the current one as selected
var selected = facetValue.isRefined ? 'selected="selected"' : '';
innerOptions.push(
'<option value="' +
facetValue.name +
'" ' +
selected +
'>' +
facetValue.name +
'</option>'
);
});
// Update the rendering
selectElement.innerHTML = innerOptions.join('\n');
} else {
$(container).hide();
}
if (attributeName == 'beschrijving') {
showHideModelArea();
}
$('#' + attributeName + '-select').selectpicker('refresh');
},
};
};
@vvo helped me with widget that accepts 1 value.
I get this error:
Uncaught Error: beschrijving is not defined in the disjunctiveFacets attribute of the helper configuration
I've tried multiple variations of facet settings in the getConfiguration part and in the search init part.
What am I doing wrong? Or is there already a
Hi @Maaark,
I don't know if this issue is still relevant but I would say that with v2, you could implement a new widget with the refinement list factory (to get the multi selection) and implement the rendering with a <select>.
I hope that it helps. I will close this issue if I don't any answer, otherwise I'm very happy to continue the discussion.
Hi @bobylito,
I am facing the same problem regarding making a custom widget that uses a
Thanks
Here's an example: https://codesandbox.io/s/m51rloxwv9?module=%2Fsrc%2FrefinementSelect.js
It was indeed a bit harder than I expected, but this works
Thank you @Haroenv.