diff --git a/docs/components/forms/multiselect.md b/docs/components/forms/multiselect.md index 846cd4ff..17aa8b6f 100644 --- a/docs/components/forms/multiselect.md +++ b/docs/components/forms/multiselect.md @@ -43,6 +43,7 @@ leitura da documentação. :args :events :component="CdsMultiselect" + @update:modelValue="handleUpdate" /> --- @@ -101,4 +102,8 @@ const args = ref({ trackBy: 'title', variant: 'green', }); + +const handleUpdate = (value) => { + args.value.modelValue = value; +}; diff --git a/package-lock.json b/package-lock.json index 28399dd2..3a5fb6d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sysvale/cuida", - "version": "3.156.1", + "version": "3.158.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sysvale/cuida", - "version": "3.156.1", + "version": "3.158.1", "dependencies": { "@popperjs/core": "^2.11.6", "@sysvale/cuida-icons": "^1.18.0", diff --git a/package.json b/package.json index 9100fbf6..57f3aae2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sysvale/cuida", - "version": "3.158.0", + "version": "3.158.1", "description": "A design system built by Sysvale, using storybook and Vue components", "repository": { "type": "git", diff --git a/src/components/Multiselect.vue b/src/components/Multiselect.vue index f52c70e4..488e2335 100644 --- a/src/components/Multiselect.vue +++ b/src/components/Multiselect.vue @@ -126,7 +126,7 @@ :option="option" :option-field="optionsField" > - {{ option[optionsField] }} + {{ option?.[optionsField] }} @@ -288,7 +288,6 @@ export default { data() { return { - selectedValue: this.$attrs.modelValue || [], internalOptions: clone(this.options), groupValues: null, groupLabel: null, @@ -301,6 +300,33 @@ export default { }, computed: { + selectedValue: { + get() { + return this.modelValue || []; + }, + set(value) { + if (!Array.isArray(value)) return; + + const cleaned = clone(value); + cleaned.forEach(val => delete val.isSelected); + this.indeterminate = value.length > 0 && value.length < this.options.length; + + /** + * Evento utilizado para implementar o v-model. + * @event input + * @type {Event} + */ + this.$emit('input', cleaned); + + /** + * Evento que indica que o valor do Multiselect foi alterado + * @event update:modelValue + * @type {Event} + */ + this.$emit('update:modelValue', cleaned); + } + }, + hasSlots() { return !!Object.keys(this.$slots).length; }, @@ -312,7 +338,7 @@ export default { selectedFancyMessage() { return (qty) => { if (qty === 1) { - return this.selectedValue[0][this.optionsField]; + return this.selectedValue?.[0]?.[this.optionsField]; } return `${qty} opções selecionadas`; }; @@ -365,23 +391,13 @@ export default { }, }, watch: { - selectedValue(values) { - const cleanedValues = clone(values); - cleanedValues.forEach((val) => delete val.isSelected); - this.indeterminate = values.length > 0 && values.length < this.options.length; - /** - * Evento utilizado para implementar o v-model. - * @event input - * @type {Event} - */ - this.$emit('input', cleanedValues); - - /** - * Evento que indica que o valor do Multiselect foi alterado - * @event update:modelValue - * @type {Event} - */ - this.$emit('update:modelValue', cleanedValues); + modelValue: { + handler(newValue) { + if (!newValue || newValue.length === 0) { + this.updateRenderOptions(); + } + }, + deep: true }, isAllItemsSelected(newValue) { @@ -400,12 +416,27 @@ export default { const input = document.getElementById(`select-all-input-id-${this.uniqueKey}`); input.indeterminate = newValue; }, + + options: { + handler(newOptions) { + this.internalOptions = clone(newOptions || []); + + if (this.selectedValue?.length) { + this.updateRenderOptions(); + } + }, + deep: true, + immediate: true, + }, }, mounted() { if (!this.modelValue || this.modelValue.length === 0) return; - this.selectedValue = this.modelValue; + this.selectedValue = Array.isArray(this.modelValue) + ? this.modelValue + : []; + this.updateRenderOptions(); this.indeterminate = this.hasSelectedValues && this.selectedValue.length < this.options.length; }, @@ -484,10 +515,19 @@ export default { addItemViaCustomCheckbox(option) { option.isSelected = !option.isSelected; - this.selectedValue = [ - ...this.selectedValue, - option, - ]; + + const isAlreadySelected = this.selectedValue.some( + item => item[this.optionsField] === option[this.optionsField] + ); + + if (isAlreadySelected) { + this.selectedValue = this.selectedValue.filter( + item => item[this.optionsField] !== option[this.optionsField] + ); + return; + } + + this.selectedValue = [...this.selectedValue, option]; }, handleClose() { @@ -510,6 +550,9 @@ export default { this.groupValues = null; this.groupLabel = null; + + this.selectAllValue = false; + this.indeterminate = false; return; }