<template> <Multiselect v-model="selection" :class="{ multiple }" :options="options" :allow-empty="true" track-by="label" label="label" :reset-after="false" select-label="" selected-label="" deselect-label="" :searchable="false" :placeholder="placeholder" :clear-on-select="false" :preserve-search="true" :multiple="multiple" :disabled="loading" @select="select" @remove="remove" @close="close" > <template slot="option" slot-scope="props" > <span :title="props.option.label">{{ props.option.label }}</span> </template> <template v-if="multiple" slot="selection" slot-scope="{ values }" > <span v-if="values && values.length > 1" class="multiselect__single" > {{ values.length }} options sélectionnées </span> <span v-else class="multiselect__single" >{{ currentSelectionLabel || selection.label }}</span> </template> </Multiselect> </template> <script> import Multiselect from 'vue-multiselect'; export default { name: 'DropdownMenuItem', components: { Multiselect }, props: { placeholder: { type: String, default: 'Sélectionnez une valeur' }, options: { type: Array, default: () => { return []; } }, loading: { type: Boolean, default: false }, multiple: { type: Boolean, default: false }, currentSelection: { type: [String, Array, Boolean], default: null, }, defaultFilter: { type: [String, Array, Boolean], default: null, } }, data() { return { selection: null, }; }, computed: { /** * Get the label of an option to work with project attributes options as JSON */ currentSelectionLabel() { const option = this.options.find(opt => opt.value === this.currentSelection); return option ? option.label : ''; } }, watch: { selection: { deep: true, handler(newValue) { if (!newValue) { this.selection = this.options[0]; this.$emit('filter', this.selection); } } }, currentSelection(newValue) { this.updateSelection(newValue); }, }, created() { if (this.currentSelection !== null) { this.selection = this.options.find(opt => opt.value === this.currentSelection); } else { this.selection = this.options[0]; } }, methods: { select(e) { this.$emit('filter', e); }, remove(e) { this.$emit('remove', e); }, close() { this.$emit('close', this.selection); }, /** * Normalizes the input value(s) to an array of strings. * This handles both single string inputs and comma-separated strings, converting them into an array. * * @param {String|Array} value - The input value to normalize, can be a string or an array of strings. * @return {Array} An array of strings representing the input values. */ normalizeValues(value) { // If the value is a string and contains commas, split it into an array; otherwise, wrap it in an array. return typeof value === 'string' ? (value.includes(',') ? value.split(',') : [value]) : value; }, /** * Updates the current selection based on new value, ensuring compatibility with multiselect. * This method processes the new selection value, accommodating both single and multiple selections, * and updates the internal `selection` state with the corresponding option objects from `options`. * * @param {String|Array} value - The new selection value(s), can be a string or an array of strings. */ // Check if the component is in multiple selection mode and the new value is provided. updateSelection(value) { if (this.multiple && value) { // Normalize the value to an array format, accommodating both single and comma-separated values. const normalizedValues = this.normalizeValues(value); // Map each value to its corresponding option object based on the 'value' field. this.selection = normalizedValues.map(value => this.options.find(option => option.value === value) ); } else { // For single selection mode or null value, find the option object that matches the value. this.selection = this.options.find(option => option.value === value); } } } }; </script> <style> #filters-container .multiple .multiselect__option--selected:not(:hover) { background-color: #e8e8e8 !important; } #filters-container .multiselect--disabled .multiselect__select { background: 0, 0 !important; } </style>