diff --git a/app/components/form/multiple_select_component.html.erb b/app/components/form/multiple_select_component.html.erb
index 58bb6f3098..79f8efaaa2 100644
--- a/app/components/form/multiple_select_component.html.erb
+++ b/app/components/form/multiple_select_component.html.erb
@@ -3,6 +3,7 @@
data-multiple-select-options-value="<%= @options %>"
data-multiple-select-selected-items-value="<%= @selected_items %>"
data-multiple-select-placeholder-term-value="<%= @placeholder_term %>"
+ data-multiple-select-show-all-option-value="<%= @show_all_option %>"
data-multiple-select-with-options-value="true">
@@ -18,6 +19,18 @@
DATA_LABEL
+ <% if @show_all_option %>
+
+
+
+
+
+
+ DATA_LABEL
+
+
+ <% end %>
+
<%= @form.select @name, {}, { multiple: true } , {
data: { "multiple-select-target": "select", } , class: "form-control-lg form-select form-select-lg input-group-lg"
} %>
diff --git a/app/components/form/multiple_select_component.rb b/app/components/form/multiple_select_component.rb
index 4df7c864bc..c2f0725c1d 100644
--- a/app/components/form/multiple_select_component.rb
+++ b/app/components/form/multiple_select_component.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
class Form::MultipleSelectComponent < ViewComponent::Base
- def initialize(form:, name:, options:, selected_items:, render_option_subtext: false, placeholder_term: nil)
+ def initialize(form:, name:, options:, selected_items:, render_option_subtext: false, placeholder_term: nil, show_all_option: false)
@form = form
@name = name
@options = options.to_json
@selected_items = selected_items
@render_option_subtext = render_option_subtext
@placeholder_term = placeholder_term
+ @show_all_option = show_all_option
end
end
diff --git a/app/javascript/controllers/multiple_select_controller.js b/app/javascript/controllers/multiple_select_controller.js
index 1ebd2dd6ec..574d4cf638 100644
--- a/app/javascript/controllers/multiple_select_controller.js
+++ b/app/javascript/controllers/multiple_select_controller.js
@@ -2,7 +2,7 @@ import { Controller } from '@hotwired/stimulus'
import TomSelect from 'tom-select'
export default class extends Controller {
- static targets = ['select', 'option', 'item']
+ static targets = ['select', 'option', 'item', 'hiddenItem', 'showAllOption'] // add 'selectAllBtn' if going with button
static values = {
options: Array,
selectedItems: Array,
@@ -10,7 +10,8 @@ export default class extends Controller {
placeholderTerm: {
type: String,
default: 'contact(s)'
- }
+ },
+ showAllOption: Boolean,
}
connect () {
@@ -37,11 +38,52 @@ export default class extends Controller {
const itemTemplate = this.itemTarget.innerHTML
const placeholder = `Select or search ${this.placeholderTermValue}`
+ const showAllOptionCheck = this.showAllOptionValue
+ const hiddenItemTemplate = showAllOptionCheck && this.hiddenItemTarget && this.hiddenItemTarget.innerHTML
+ const showAllOptionTemplate = showAllOptionCheck && this.showAllOptionTarget && this.showAllOptionTarget.innerHTML
+
+ // orderedOptionVals is of type (" " | number)[] - the " " could appear
+ // because using it as the value for the select/unselect all option
+ let orderedOptionVals = this.optionsValue.map(opt => opt.value)
+ if (showAllOptionCheck) {
+ // using " " as value instead of "" bc tom-select doesn't init the "" in the item list
+ orderedOptionVals = [" "].concat(orderedOptionVals)
+ }
+
+ // used to determine initial items selected by tom-select
+ const initItems = this.selectedItemsValue?.length ? this.selectedItemsValue : orderedOptionVals
+
+ const dropdownOptions = showAllOptionCheck ?
+ [{ text: "Select/Unseselect all", subtext: "", value: " ", group: ""}].concat(this.optionsValue)
+ : this.optionsValue
+
+ // const selectAllBtn = this.selectAllBtnTarget
+ // assign TomSelect instance to this.selectEl if going with button implementation
+
/* eslint-disable no-new */
new TomSelect(this.selectTarget, {
- onItemAdd: function () {
+ onItemRemove: function(value, data) {
+ // for the select/unselect all button - add in short circuit in case showAllBtn doesn't exist
+ // if (this.items.length < orderedOptionVals.length) {
+ // selectAllBtn.innerText = 'Select all'
+ // }
+
+ if (value === " ") {
+ this.clear()
+ }
+ },
+ onItemAdd: function (value) {
this.setTextboxValue('')
this.refreshOptions()
+
+ // for the select/unselect all button - add in short circuit in case showAllBtn doesn't exist
+ // if (this.items.length < orderedOptionVals.length) {
+ // selectAllBtn.innerText = 'Select all'
+ // }
+
+ if (value === " ") {
+ this.addItems(orderedOptionVals);
+ }
},
plugins: {
remove_button: {
@@ -54,21 +96,42 @@ export default class extends Controller {
uncheckedClassNames: ['form-check-input']
}
},
- options: this.optionsValue,
- items: this.selectedItemsValue,
+ options: dropdownOptions,
+ items: initItems,
placeholder,
hidePlaceholder: true,
searchField: ['text', 'group'],
render: {
option: function (data, escape) {
- let html = optionTemplate.replace(/DATA_LABEL/g, escape(data.text))
- html = html.replace(/DATA_SUB_TEXT/g, escape(data.subtext))
+ let html
+
+ if (showAllOptionCheck && data && data.value === " ") {
+ html = showAllOptionTemplate.replace(/DATA_LABEL/g, escape(data.text))
+ } else {
+ html = optionTemplate.replace(/DATA_LABEL/g, escape(data.text))
+ html = html.replace(/DATA_SUB_TEXT/g, escape(data.subtext))
+ }
return html
},
item: function (data, escape) {
- return itemTemplate.replace(/DATA_LABEL/g, escape(data.text))
+ return showAllOptionCheck && data.value === " " ? hiddenItemTemplate : itemTemplate.replace(/DATA_LABEL/g, escape(data.text))
}
}
})
}
+
+ // action for the select/unselect all button - add in short circuit in case showAllBtn or selectEl doesn't exist
+ // toggleSelectAll() {
+ // if (!this.selectEl || !this.selectAllBtnTarget) return
+
+ // const checkedStatus = this.selectEl.items.length === Object.keys(this.selectEl.options).length ? "all" : "not-all"
+
+ // if (checkedStatus === "all") {
+ // this.selectEl.clear()
+ // this.selectAllBtnTarget.textContent = "Select all"
+ // } else {
+ // this.selectEl.addItems(this.optionsValue.map(opt => opt.value))
+ // this.selectAllBtnTarget.textContent = "Unselect all"
+ // }
+ // }
}
diff --git a/app/views/case_contacts/form/_contact_types.html.erb b/app/views/case_contacts/form/_contact_types.html.erb
index 1f91e5f1d1..517d71b65b 100644
--- a/app/views/case_contacts/form/_contact_types.html.erb
+++ b/app/views/case_contacts/form/_contact_types.html.erb
@@ -5,6 +5,7 @@
name: :contact_type_ids,
options: options.decorate.map { |ct| ct.hash_for_multi_select_with_cases(casa_cases&.pluck(:id)) },
selected_items: selected_items,
- render_option_subtext: true
+ render_option_subtext: true,
+ show_all_option: true,
)) %>