mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-21 00:47:26 +00:00
106 lines
3.0 KiB
JavaScript
106 lines
3.0 KiB
JavaScript
import { Controller } from "stimulus";
|
|
|
|
export default class extends Controller {
|
|
static values = {
|
|
url: String,
|
|
};
|
|
|
|
connect() {
|
|
if (typeof $ === "undefined" || typeof $.fn.select2 === "undefined") {
|
|
console.error("Select2 AJAX Controller: jQuery or Select2 not loaded");
|
|
return;
|
|
}
|
|
|
|
const ajaxUrl = this.urlValue;
|
|
if (!ajaxUrl) return;
|
|
|
|
const selectName = this.element.name;
|
|
const selectId = this.element.id;
|
|
const isMultiple = this.element.multiple;
|
|
|
|
const container = document.createElement("div");
|
|
container.dataset.select2HiddenContainer = "true";
|
|
|
|
this.element.replaceWith(container);
|
|
|
|
// select2 methods are accessible via jQuery
|
|
// Plus, ajax calls with multi-select require a hidden input in select2
|
|
const $select2Input = $('<input type="hidden" />');
|
|
$select2Input.attr("id", selectId);
|
|
container.appendChild($select2Input[0]);
|
|
|
|
// IN-MEMORY cache to avoid repeated ajax calls for same query/page
|
|
const ajaxCache = {};
|
|
|
|
const select2Options = {
|
|
ajax: {
|
|
url: ajaxUrl,
|
|
dataType: "json",
|
|
quietMillis: 300,
|
|
data: function (term, page) {
|
|
return {
|
|
q: term || "",
|
|
page: page || 1,
|
|
};
|
|
},
|
|
transport: function (params) {
|
|
const term = params.data.q || "";
|
|
const page = params.data.page || 1;
|
|
const cacheKey = `${term}::${page}`;
|
|
|
|
if (ajaxCache[cacheKey]) {
|
|
params.success(ajaxCache[cacheKey]);
|
|
return;
|
|
}
|
|
|
|
const request = $.ajax(params);
|
|
|
|
request.then((data) => {
|
|
ajaxCache[cacheKey] = data;
|
|
params.success(data);
|
|
});
|
|
|
|
return request;
|
|
},
|
|
results: function (data, _page) {
|
|
return {
|
|
results: data.results || [],
|
|
more: (data.pagination && data.pagination.more) || false,
|
|
};
|
|
},
|
|
},
|
|
allowClear: true,
|
|
minimumInputLength: 0,
|
|
multiple: isMultiple,
|
|
width: "100%",
|
|
formatResult: (item) => item.text,
|
|
formatSelection: (item) => item.text,
|
|
};
|
|
|
|
// Initialize select2 with ajax options on hidden input
|
|
$select2Input.select2(select2Options);
|
|
|
|
// Rails-style array submission requires multiple hidden inputs with same name
|
|
const syncHiddenInputs = (values) => {
|
|
// remove old inputs
|
|
container.querySelectorAll(`input[name="${selectName}"]`).forEach((e) => e.remove());
|
|
|
|
values.forEach((value) => {
|
|
const input = document.createElement("input");
|
|
input.type = "hidden";
|
|
input.name = selectName;
|
|
input.value = value;
|
|
container.appendChild(input);
|
|
});
|
|
};
|
|
|
|
// On change → rebuild hidden inputs to submit filter values
|
|
$select2Input.on("change", () => {
|
|
const valuesString = $select2Input.val() || "";
|
|
const values = valuesString.split(",") || [];
|
|
|
|
syncHiddenInputs(Array.isArray(values) ? values : [values]);
|
|
});
|
|
}
|
|
}
|