From a6974adc89610e8efbbe062a0f2558042946510f Mon Sep 17 00:00:00 2001 From: LrxGaelle Date: Tue, 10 Oct 2023 15:26:59 +0200 Subject: [PATCH] MINOR: Feature/search in select (#315) * add search bar into BIMDataSelect component * add documentation for search bar into BIMDataSelect * delete unused component * delete template tag into BIMDataSelect file * fix search bar width * compute this.searchText.toLowerCase() * add reset search methods * add reset search documentation * refactoring --- .../BIMDataSelect/BIMDataSelect.vue | 26 ++--- .../BIMDataSelect/BIMDataSelectMulti.vue | 94 ++++++++++++++----- .../BIMDataSelect/BIMDataSelectSingle.vue | 94 ++++++++++++++----- .../BIMDataSelect/_BIMDataSelect.scss | 1 - src/web/views/Components/Select/Select.vue | 78 ++++++++++++++- src/web/views/Components/Select/props-data.js | 83 ++++++++-------- src/web/views/Components/Select/slots-data.js | 8 ++ 7 files changed, 277 insertions(+), 107 deletions(-) create mode 100644 src/web/views/Components/Select/slots-data.js diff --git a/src/BIMDataComponents/BIMDataSelect/BIMDataSelect.vue b/src/BIMDataComponents/BIMDataSelect/BIMDataSelect.vue index 45feed1b..efe32e1a 100644 --- a/src/BIMDataComponents/BIMDataSelect/BIMDataSelect.vue +++ b/src/BIMDataComponents/BIMDataSelect/BIMDataSelect.vue @@ -1,13 +1,5 @@ - - diff --git a/src/BIMDataComponents/BIMDataSelect/BIMDataSelectMulti.vue b/src/BIMDataComponents/BIMDataSelect/BIMDataSelectMulti.vue index 1847dd91..87fcca18 100644 --- a/src/BIMDataComponents/BIMDataSelect/BIMDataSelectMulti.vue +++ b/src/BIMDataComponents/BIMDataSelect/BIMDataSelectMulti.vue @@ -7,7 +7,7 @@ 'not-empty': modelValue.length > 0, }" :style="{ width }" - v-clickaway="() => (isOpen = false)" + v-clickaway="away" >
@@ -21,29 +21,43 @@
-
    -
  • - - -
  • -
+
+ +
+ +
+
    +
  • + + +
  • +
+
@@ -94,17 +108,40 @@ export default { type: Boolean, default: false, }, + search: { + type: Boolean, + default: false, + }, + searchPlaceholder: { + type: String, + default: "Search", + }, + isResetSearch: { + type: Boolean, + default: false, + }, }, emits: ["update:modelValue"], data() { return { isOpen: false, + searchText: "", }; }, computed: { displayedValue() { return this.modelValue.map(this.optionLabel).join(", "); }, + filteredOptions() { + if (this.searchText === "") { + return this.options; + } else { + const lowerCaseSearchText = this.searchText.toLowerCase(); + return this.options.filter(option => + option.toLowerCase().includes(lowerCaseSearchText), + ); + } + }, }, methods: { toggle() { @@ -154,6 +191,15 @@ export default { } this.$emit("update:modelValue", options); }, + resetSearch() { + if (this.isResetSearch) { + this.searchText = ""; + } + }, + away() { + this.isOpen = false; + this.resetSearch(); + }, }, }; diff --git a/src/BIMDataComponents/BIMDataSelect/BIMDataSelectSingle.vue b/src/BIMDataComponents/BIMDataSelect/BIMDataSelectSingle.vue index c36d3d05..f0f9e769 100644 --- a/src/BIMDataComponents/BIMDataSelect/BIMDataSelectSingle.vue +++ b/src/BIMDataComponents/BIMDataSelect/BIMDataSelectSingle.vue @@ -7,7 +7,7 @@ 'not-empty': modelValue !== undefined && modelValue !== null, }" :style="{ width }" - v-clickaway="() => (isOpen = false)" + v-clickaway="away" >
@@ -21,28 +21,42 @@
-
    -
  • - {{ nullLabel || "None" }} -
  • -
  • - {{ optionLabel(option) }} -
  • -
+
+ +
+ +
+
    +
  • + {{ nullLabel || "None" }} +
  • +
  • + {{ optionLabel(option) }} +
  • +
+
@@ -95,17 +109,40 @@ export default { type: Boolean, default: false, }, + search: { + type: Boolean, + default: false, + }, + searchPlaceholder: { + type: String, + default: "Search", + }, + isResetSearch: { + type: Boolean, + default: false, + }, }, emits: ["update:modelValue"], data() { return { isOpen: false, + searchText: "", }; }, computed: { displayedValue() { return this.optionLabel(this.modelValue); }, + filteredOptions() { + if (this.searchText === "") { + return this.options; + } else { + const lowerCaseSearchText = this.searchText.toLowerCase(); + return this.options.filter(option => + option.toLowerCase().includes(lowerCaseSearchText), + ); + } + }, }, methods: { toggle() { @@ -142,16 +179,27 @@ export default { isOptionGroup(option) { return this.optionKey && option && option.optionGroup; }, + resetSearch() { + if (this.isResetSearch) { + this.searchText = ""; + } + }, onOptionClick(option) { if (this.optionKey && (option.disabled || option.optionGroup)) { return; } this.$emit("update:modelValue", option); + this.resetSearch(); this.isOpen = false; }, onNullValueClick() { this.$emit("update:modelValue", null); + this.resetSearch(); + this.isOpen = false; + }, + away() { this.isOpen = false; + this.resetSearch(); }, }, }; diff --git a/src/BIMDataComponents/BIMDataSelect/_BIMDataSelect.scss b/src/BIMDataComponents/BIMDataSelect/_BIMDataSelect.scss index 5b84b8ca..fc3e7d04 100644 --- a/src/BIMDataComponents/BIMDataSelect/_BIMDataSelect.scss +++ b/src/BIMDataComponents/BIMDataSelect/_BIMDataSelect.scss @@ -71,7 +71,6 @@ top: -3px; width: 100%; max-height: 220px; - padding: calc(var(--spacing-unit) / 2) 0; overflow: auto; box-shadow: var(--box-shadow); background-color: var(--color-white); diff --git a/src/web/views/Components/Select/Select.vue b/src/web/views/Components/Select/Select.vue index bca94b51..ad48e91c 100644 --- a/src/web/views/Components/Select/Select.vue +++ b/src/web/views/Components/Select/Select.vue @@ -10,6 +10,7 @@ + :isResetSearch="clearSearch" + > + + Selection: @@ -37,7 +43,8 @@ @@ -101,6 +134,13 @@ +
+ Slots: + +
+
Note about 'v-model' and 'optionKey' prop: @@ -157,6 +197,8 @@ import { stringOptions, objectOptions, groupOptions } from "./option-sets"; import eventsData from "./events-data.js"; import propsData from "./props-data"; +import slotsData from "./slots-data"; + // Components import Code from "../../Elements/Code/Code.vue"; import ComponentCode from "../../Elements/ComponentCode/ComponentCode.vue"; @@ -170,7 +212,9 @@ export default { return { isDisabled: false, isMulti: false, + isEmpty: false, hasNullValue: false, + clearSearch: false, optionSet: "string", options: stringOptions, optionKey: null, @@ -178,6 +222,9 @@ export default { selection: null, propsData, eventsData, + slotsData, + search: false, + searchText: "", }; }, methods: { @@ -189,6 +236,23 @@ export default { } this.isMulti = value; }, + toggleSearch(value) { + this.search = value; + if (!this.search) { + this.clearSearch = false; + } + }, + toggleEmpty(value) { + this.isEmpty = value; + }, + toggleClearSearch(value) { + this.clearSearch = value; + }, + getEmptySlot() { + if (this.isEmpty) { + return ""; + } + }, changeOptionSet(value) { switch (value) { case "string": @@ -213,3 +277,11 @@ export default { }, }; + + diff --git a/src/web/views/Components/Select/props-data.js b/src/web/views/Components/Select/props-data.js index cc5ca34a..115ad5cf 100644 --- a/src/web/views/Components/Select/props-data.js +++ b/src/web/views/Components/Select/props-data.js @@ -1,40 +1,14 @@ /* eslint-disable */ export default [ + ["Name", "Type", "Default value", "Description"], + ["disabled", "Boolean", "false", "When true the selector will be disabled."], [ - "Name", "Type", "Default value", "Description" - ], - [ - "width", - "[String, Number]", - "100%", - "Set the selector width.", - ], - [ - "label", - "String", - "null", - "Set the selector label (placeholder)." - ], - [ - "options", - "Array", - "[]", - "Array of available options. Can be an array of strings or objects (not both at the same time).", - ], - [ - "optionKey", - "String", - "null", - "Only use this props if the 'options' props is an array of objects. " - + "Specify which field of the object represent the option value.", - ], - [ - "optionLabelKey", - "String", - "null", - "Only use this props if the 'options' props is an array of objects. " - + "Specify which field of the object represent the option label.", + "isResetSearch", + "Boolean", + "false", + "In multi-selection mode: clear search bar on click away. In single selection: clear search bar on select element or click away.", ], + ["label", "String", "null", "Set the selector label (placeholder)."], [ "modelValue", "[String, Object, Array]", @@ -47,23 +21,46 @@ export default [ "false", "Use this boolean to select multiple options from a list of options.", ], + [ + "nullLabel", + "String", + "", + "Define a custom label for `null` or `undefined` options.", + ], [ "nullValue", "Boolean", "false", - "This props has no effect in multi-selection mode. " - + "Add a 'none' value in single-selection mode.", + "This props has no effect in multi-selection mode. " + + "Add a 'none' value in single-selection mode.", ], [ - "nullLabel", + "optionKey", "String", - "", - "Define a custom label for `null` or `undefined` options." + "null", + "Only use this props if the 'options' props is an array of objects. " + + "Specify which field of the object represent the option value.", ], [ - "disabled", - "Boolean", - "false", - "When true the selector will be disabled." - ] + "optionLabelKey", + "String", + "null", + "Only use this props if the 'options' props is an array of objects. " + + "Specify which field of the object represent the option label.", + ], + [ + "options", + "Array", + "[]", + "Array of available options. Can be an array of strings or objects (not both at the same time).", + ], + ["search", "Boolean", "false", "Use this boolean to add a search bar."], + [ + "searchPlaceholder", + "String", + "Search", + "Use this props to custom search placeholder.", + ], + ["width", "[String, Number]", "100%", "Set the selector width."], + ]; diff --git a/src/web/views/Components/Select/slots-data.js b/src/web/views/Components/Select/slots-data.js new file mode 100644 index 00000000..25067498 --- /dev/null +++ b/src/web/views/Components/Select/slots-data.js @@ -0,0 +1,8 @@ +/* eslint-disable */ +export default [ + [ "Slot name", "Description" ], + [ + "empty", + "Use this slot if you need to add a custom message when the selector is empty." + ] +];