From b7adc5f551bde501c84972050fbe6cee11b3b955 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Tue, 27 Sep 2022 10:55:07 +0200 Subject: [PATCH] Create the MultipleCheckedComponent + Associate the StimulusController to this component --- .../multiple_checked_select_component.rb | 9 +++ ...ultiple_checked_select_component.html.haml | 13 +++++ .../multiple_checked_select_controller.js | 55 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 app/components/multiple_checked_select_component.rb create mode 100644 app/components/multiple_checked_select_component/multiple_checked_select_component.html.haml create mode 100644 app/webpacker/controllers/multiple_checked_select_controller.js diff --git a/app/components/multiple_checked_select_component.rb b/app/components/multiple_checked_select_component.rb new file mode 100644 index 0000000000..e452625169 --- /dev/null +++ b/app/components/multiple_checked_select_component.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class MultipleCheckedSelectComponent < ViewComponent::Base + def initialize(name:, options:, selected:) + @name = name + @options = options + @selected = selected.map(&:to_sym) + end +end diff --git a/app/components/multiple_checked_select_component/multiple_checked_select_component.html.haml b/app/components/multiple_checked_select_component/multiple_checked_select_component.html.haml new file mode 100644 index 0000000000..11464fbb1b --- /dev/null +++ b/app/components/multiple_checked_select_component/multiple_checked_select_component.html.haml @@ -0,0 +1,13 @@ +.ofn-drop-down{ data: { controller: "multiple-checked-select", "multiple-checked-select-input-name-value": @name } } + %div{ "data-multiple-checked-select-target": "button" } + %span{ class: 'icon-reorder' } + = "  #{t('admin.columns')}".html_safe + %span{ class: "icon-caret-down", "data-multiple-checked-select-target": "caret" } + %div.menu{ class: "hidden", "data-multiple-checked-select-target": "options" } + - @options.each do |option| + - classes = @selected.include?(option[1]) ? "selected" : "" + %div.menu_item{ class: classes, "data-multiple-checked-select-target": "option", "data-value": option[1] } + %span.check + %span.name{id: option[1]} + = option[0] + %div{style: "display: none;", "data-multiple-checked-select-target": "inputs"} diff --git a/app/webpacker/controllers/multiple_checked_select_controller.js b/app/webpacker/controllers/multiple_checked_select_controller.js new file mode 100644 index 0000000000..5dde603d1d --- /dev/null +++ b/app/webpacker/controllers/multiple_checked_select_controller.js @@ -0,0 +1,55 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["button", "caret", "options", "option", "inputs"]; + static values = { inputName: String }; + + connect() { + this.buttonTarget.addEventListener("click", this.toggleOptions); + this.optionTargets.forEach((option) => { + option.addEventListener("click", (e) => + this.selectOption(e, option.dataset.value) + ); + }); + this.buildInputs(); + document.addEventListener("click", this.closeOptions); + } + + disconnect() { + document.removeEventListener("click", this.closeOptions); + } + + toggleOptions = () => { + this.optionsTarget.classList.toggle("hidden"); + this.caretTarget.classList.toggle("icon-caret-down"); + this.caretTarget.classList.toggle("icon-caret-up"); + }; + + closeOptions = (e) => { + if (!this.element.contains(e.target)) { + this.optionsTarget.classList.add("hidden"); + this.caretTarget.classList.remove("icon-caret-up"); + this.caretTarget.classList.add("icon-caret-down"); + } + }; + + selectOption = (event, value) => { + this.optionTargets + .find((option) => option.dataset.value === value) + .classList.toggle("selected"); + this.buildInputs(); + }; + + buildInputs = () => { + this.inputsTarget.innerHTML = ""; + this.optionTargets + .filter((option) => option.classList.contains("selected")) + .forEach((option) => { + const input = document.createElement("input"); + input.type = "hidden"; + input.name = this.inputNameValue + "[]"; + input.value = option.dataset.value; + this.inputsTarget.appendChild(input); + }); + }; +}