Multi selection combos working

This commit is contained in:
Jorge Manrubia
2025-09-18 17:13:05 +02:00
parent 8d2a191a91
commit cb7d260545
4 changed files with 126 additions and 36 deletions
@@ -0,0 +1,81 @@
import { Controller } from "@hotwired/stimulus"
import { toSentence } from "helpers/text_helpers"
export default class extends Controller {
#hiddenField
static targets = [ "label", "item", "hiddenFieldTemplate" ]
static values = {
selectPropertyName: { type: String, default: "aria-checked" },
defaultValue: String,
noSelectionLabel: { type: String, default: "No selection" }
}
connect() {
this.labelTarget.textContent = this.#selectedLabel
}
change(event) {
const item = event.target.closest("[role='checkbox']")
if (item) {
this.#toggleSelection(item)
}
}
get #selectedLabel() {
const selectedValues = this.#selectedValues()
if (selectedValues.length === 0) {
return this.noSelectionLabelValue
}
const labels = this.#selectedItems().map(item => item.dataset.multiSelectionComboboxLabel)
return toSentence(labels, {
two_words_connector: " or ",
last_word_connector: ", or "
})
}
#toggleSelection(item) {
const isSelected = item.getAttribute(this.selectPropertyNameValue) === "true"
if (isSelected) {
item.setAttribute(this.selectPropertyNameValue, "false")
} else {
item.setAttribute(this.selectPropertyNameValue, "true")
}
this.#updateHiddenFields()
this.labelTarget.textContent = this.#selectedLabel
}
#updateHiddenFields() {
this.#clearHiddenFields()
this.#addHiddenFields()
}
#selectedItems() {
return this.itemTargets.filter(item =>
item.getAttribute(this.selectPropertyNameValue) === "true"
)
}
#selectedValues() {
return this.#selectedItems().map(item => item.dataset.multiSelectionComboboxValue)
}
#clearHiddenFields() {
this.element.querySelectorAll('input[type="hidden"]').forEach(field => {
if (field !== this.hiddenField) {
field.remove()
}
})
}
#addHiddenFields() {
this.#selectedValues().forEach(value => {
const [field] = this.hiddenFieldTemplateTarget.content.cloneNode(true).children
field.value = value
this.element.appendChild(field)
})
}
}
+24
View File
@@ -11,3 +11,27 @@ export function normalizeFilteredText(string) {
export function filterMatches(text, potentialMatch) {
return normalizeFilteredText(text).includes(normalizeFilteredText(potentialMatch))
}
export function toSentence(array, options = {}) {
const defaultConnectors = {
words_connector: ", ",
two_words_connector: " and ",
last_word_connector: ", and "
}
const connectors = { ...defaultConnectors, ...options }
if (array.length === 0) {
return ""
}
if (array.length === 1) {
return array[0]
}
if (array.length === 2) {
return array.join(connectors.two_words_connector)
}
return array.slice(0, -1).join(connectors.words_connector) + connectors.last_word_connector + array[array.length - 1]
}