Skip to content

Commit 7154254

Browse files
authoredNov 10, 2024··
fix(InputMenu/SelectMenu): use by prop to compare objects & support dot notation in value-attribute (#2566)
1 parent 49f85d5 commit 7154254

File tree

2 files changed

+60
-24
lines changed

2 files changed

+60
-24
lines changed
 

‎src/runtime/components/forms/InputMenu.vue

+23-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
v-slot="{ active, selected, disabled: optionDisabled }"
4949
:key="index"
5050
as="template"
51-
:value="valueAttribute ? option[valueAttribute] : option"
51+
:value="valueAttribute ? accessor(option, valueAttribute) : option"
5252
:disabled="option.disabled"
5353
>
5454
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, selected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]">
@@ -104,6 +104,7 @@ import {
104104
import { computedAsync, useDebounceFn } from '@vueuse/core'
105105
import { defu } from 'defu'
106106
import { twMerge, twJoin } from 'tailwind-merge'
107+
import { isEqual } from 'ohash'
107108
import UIcon from '../elements/Icon.vue'
108109
import UAvatar from '../elements/Avatar.vue'
109110
import { useUI } from '../../composables/useUI'
@@ -308,8 +309,28 @@ export default defineComponent({
308309
return
309310
}
310311
312+
function getValue(value: any) {
313+
if (props.valueAttribute) {
314+
return accessor(value, props.valueAttribute)
315+
}
316+
317+
return value
318+
}
319+
320+
function compareValues(value1: any, value2: any) {
321+
if (props.by && typeof value1 === 'object' && typeof value2 === 'object') {
322+
return isEqual(value1[props.by], value2[props.by])
323+
}
324+
return isEqual(value1, value2)
325+
}
326+
311327
if (props.valueAttribute) {
312-
const option = options.value.find(option => option[props.valueAttribute] === props.modelValue)
328+
const option = options.value.find((option) => {
329+
const optionValue = getValue(option)
330+
331+
return compareValues(optionValue, props.modelValue)
332+
})
333+
313334
return option ? accessor(option, props.optionAttribute) : null
314335
} else {
315336
return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : accessor(props.modelValue as Record<string, any>, props.optionAttribute)

‎src/runtime/components/forms/SelectMenu.vue

+37-22
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
v-slot="{ active, selected: optionSelected, disabled: optionDisabled }"
7272
:key="index"
7373
as="template"
74-
:value="valueAttribute ? option[valueAttribute] : option"
74+
:value="valueAttribute ? accessor(option, valueAttribute) : option"
7575
:disabled="option.disabled"
7676
>
7777
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive, optionSelected && uiMenu.option.selected, optionDisabled && uiMenu.option.disabled]">
@@ -140,6 +140,7 @@ import {
140140
import { computedAsync, useDebounceFn } from '@vueuse/core'
141141
import { defu } from 'defu'
142142
import { twMerge, twJoin } from 'tailwind-merge'
143+
import { isEqual } from 'ohash'
143144
import UIcon from '../elements/Icon.vue'
144145
import UAvatar from '../elements/Avatar.vue'
145146
import { useUI } from '../../composables/useUI'
@@ -364,39 +365,53 @@ export default defineComponent({
364365
})
365366
366367
const selected = computed(() => {
367-
if (props.multiple) {
368-
if (!Array.isArray(props.modelValue) || !props.modelValue.length) {
369-
return []
368+
function compareValues(value1: any, value2: any) {
369+
if (props.by && typeof value1 === 'object' && typeof value2 === 'object') {
370+
return isEqual(value1[props.by], value2[props.by])
370371
}
372+
return isEqual(value1, value2)
373+
}
371374
375+
function getValue(value: any) {
372376
if (props.valueAttribute) {
373-
return options.value.filter(option => (props.modelValue as any[]).includes(option[props.valueAttribute]))
377+
return accessor(value, props.valueAttribute)
374378
}
375-
return options.value.filter(option => (props.modelValue as any[]).includes(option))
379+
380+
return value
376381
}
377382
378-
if (props.valueAttribute) {
379-
return options.value.find(option => option[props.valueAttribute] === props.modelValue)
383+
if (props.multiple) {
384+
const modelValue = props.modelValue
385+
if (!Array.isArray(modelValue) || !modelValue.length) {
386+
return []
387+
}
388+
389+
return options.value.filter((option) => {
390+
const optionValue = getValue(option)
391+
return modelValue.some(value => compareValues(value, optionValue))
392+
})
380393
}
381-
return options.value.find(option => option === props.modelValue)
394+
395+
return options.value.find((option) => {
396+
const optionValue = getValue(option)
397+
return compareValues(optionValue, toRaw(props.modelValue))
398+
}) ?? props.modelValue
382399
})
383400
384401
const label = computed(() => {
385-
if (props.multiple) {
386-
if (Array.isArray(props.modelValue) && props.modelValue.length) {
387-
return `${selected.value.length} selected`
388-
} else {
389-
return null
390-
}
391-
} else if (props.modelValue !== undefined && props.modelValue !== null) {
392-
if (props.valueAttribute) {
393-
return accessor(selected.value, props.optionAttribute) ?? null
394-
} else {
395-
return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : accessor(props.modelValue as Record<string, any>, props.optionAttribute)
396-
}
402+
if (!selected.value) return null
403+
404+
if (props.valueAttribute) {
405+
return accessor(selected.value as Record<string, any>, props.optionAttribute)
406+
}
407+
408+
if (Array.isArray(props.modelValue) && props.modelValue.length) {
409+
return `${props.modelValue.length} selected`
410+
} else if (['string', 'number'].includes(typeof props.modelValue)) {
411+
return props.modelValue
397412
}
398413
399-
return null
414+
return accessor(props.modelValue as Record<string, any>, props.optionAttribute)
400415
})
401416
402417
const selectClass = computed(() => {

0 commit comments

Comments
 (0)
Please sign in to comment.