Using select2 with sortBy widget

I’m building an Algolia plugin for our Woocommerce store. I ran into a problem when I was trying to use select2 to be able to style the sortBy widgets’ dropdown as we desire. The original select didn’t seem to get any ‘change’ events. My best guess is that when creating the eventListener on the first render it gets attached to the original HTML select element and that select2 removes that and replaces it with a new one… So I came up with a solution that uses a custom event on the document. It feels a little “hacky” so I figured I’d just see if there is a better way to do it?

import instantsearch from "instantsearch.js";

// Create the render function
const renderSortBy = (renderOptions, isFirstRender) => {
  const { options, currentRefinement, hasNoResults, refine, widgetParams } = renderOptions;

  if (isFirstRender) {
    const select = document.createElement("select");
    select.classList.add("sortby-select");

    document.addEventListener("sortby:change", (event) => {
      refine(event.detail);
    });

    widgetParams.container.appendChild(select);
  }

  const select = widgetParams.container.querySelector(".sortby-select");

  select.disabled = hasNoResults;

  select.innerHTML = `
    ${options
      .map(
        (option) => `
          <option
            value="${option.value}"
            ${option.value === currentRefinement ? "selected" : ""}
          >
            ${option.label}
          </option>
        `
      )
      .join("")}
  `;
};

// Create the custom widget
const mkSortBy = instantsearch.connectors.connectSortBy(renderSortBy);

const _default = mkSortBy;
export { _default as default };

(function ($) {
  $(document).ready(function () {
    $(".sortby-select").select2({
      minimumResultsForSearch: Infinity,
    });

    $(".sortby-select").on("change", function (e) {
      let event = new CustomEvent("sortby:change", { detail: e.target.value });
      document.dispatchEvent(event);
    });
  });
})(jQuery);

I haven’t tried to override the sortBy widget personally, but this custom sortBy widget that renders a UL instead of a select component may help you sanity check your events. If it looks like it matches up, I’d say you’re probably correct its an an internal implementation detail of select2.

By the way, you’re more than welcome to use this custom UL widget if it solves your problem around styling, but I totally understand if you’ve normalized around select2 for your application.

Thank you for your suggestion! I have chosen to go with the “hack” that I came up with though. :slight_smile:

1 Like