From 53df9d9a8cd6850803bdafc7ef6efe4e7404d334 Mon Sep 17 00:00:00 2001 From: kyyy <60952577+rdjanuar@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:25:31 +0700 Subject: [PATCH] feat(InputMenu/SelectMenu): add support for `dot notation` in `by` prop (#2607) --- src/runtime/components/forms/InputMenu.vue | 28 ++++++++++++++--- src/runtime/components/forms/SelectMenu.vue | 34 +++++++++++++++------ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/runtime/components/forms/InputMenu.vue b/src/runtime/components/forms/InputMenu.vue index 2264b503..3fce532d 100644 --- a/src/runtime/components/forms/InputMenu.vue +++ b/src/runtime/components/forms/InputMenu.vue @@ -293,6 +293,24 @@ export default defineComponent({ const size = computed(() => sizeButtonGroup.value ?? sizeFormGroup.value) + const by = computed(() => { + if (!props.by) return undefined + + if (typeof props.by === 'function') { + return props.by + } + + const key = props.by + const hasDot = key.indexOf('.') + if (hasDot > 0) { + return (a: any, z: any) => { + return accessor(a, key) === accessor(z, key) + } + } + + return key + }) + const internalQuery = ref('') const query = computed({ get() { @@ -305,9 +323,7 @@ export default defineComponent({ }) const label = computed(() => { - if (!props.modelValue) { - return - } + if (!props.modelValue) return null function getValue(value: any) { if (props.valueAttribute) { @@ -318,7 +334,7 @@ export default defineComponent({ } function compareValues(value1: any, value2: any) { - if (props.by && typeof value1 === 'object' && typeof value2 === 'object') { + if (by.value && typeof by.value !== 'function' && typeof value1 === 'object' && typeof value2 === 'object') { return isEqual(value1[props.by], value2[props.by]) } return isEqual(value1, value2) @@ -507,7 +523,9 @@ export default defineComponent({ query, accessor, onUpdate, - onQueryChange + onQueryChange, + // eslint-disable-next-line vue/no-dupe-keys + by } } }) diff --git a/src/runtime/components/forms/SelectMenu.vue b/src/runtime/components/forms/SelectMenu.vue index eac8cbc3..27ec393e 100644 --- a/src/runtime/components/forms/SelectMenu.vue +++ b/src/runtime/components/forms/SelectMenu.vue @@ -348,6 +348,24 @@ export default defineComponent({ const [trigger, container] = usePopper(popper.value) + const by = computed(() => { + if (!props.by) return undefined + + if (typeof props.by === 'function') { + return props.by + } + + const key = props.by + const hasDot = key.indexOf('.') + if (hasDot > 0) { + return (a: any, z: any) => { + return accessor(a, key) === accessor(z, key) + } + } + + return key + }) + const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props }) const { emitFormBlur, emitFormChange, inputId, color, size: sizeFormGroup, name } = useFormGroup(props, config) @@ -366,8 +384,8 @@ export default defineComponent({ const selected = computed(() => { function compareValues(value1: any, value2: any) { - if (props.by && typeof value1 === 'object' && typeof value2 === 'object') { - return isEqual(value1[props.by], value2[props.by]) + if (by.value && typeof by.value !== 'function' && typeof value1 === 'object' && typeof value2 === 'object') { + return isEqual(value1[by.value], value2[by.value]) } return isEqual(value1, value2) } @@ -399,16 +417,12 @@ export default defineComponent({ }) const label = computed(() => { - if (!selected.value) return null - - if (props.valueAttribute) { - return accessor(selected.value as Record, props.optionAttribute) - } + if (!props.modelValue) return null if (Array.isArray(props.modelValue) && props.modelValue.length) { return `${props.modelValue.length} selected` } else if (['string', 'number'].includes(typeof props.modelValue)) { - return props.modelValue + return props.valueAttribute ? accessor(selected.value, props.optionAttribute) : props.modelValue } return accessor(props.modelValue as Record, props.optionAttribute) @@ -612,7 +626,9 @@ export default defineComponent({ // eslint-disable-next-line vue/no-dupe-keys query, onUpdate, - onQueryChange + onQueryChange, + // eslint-disable-next-line vue/no-dupe-keys + by } } })