diff --git a/packages/vuetify/src/composables/__tests__/group.spec.ts b/packages/vuetify/src/composables/__tests__/group.spec.ts index 625e89dccd4..076e29b6169 100644 --- a/packages/vuetify/src/composables/__tests__/group.spec.ts +++ b/packages/vuetify/src/composables/__tests__/group.spec.ts @@ -3,7 +3,7 @@ import { makeGroupProps, useGroup, useGroupItem } from '../group' // Utilities import { describe, expect, it } from '@jest/globals' import { mount } from '@vue/test-utils' -import { defineComponent, h, nextTick, reactive } from 'vue' +import { defineComponent, h, nextTick, reactive, useSlots } from 'vue' describe('group', () => { describe('with complex values', () => { @@ -270,7 +270,8 @@ describe('group', () => { setup (props) { // @ts-expect-error missing emit useGroup(props, Symbol.for('test')) - return () => h('div', [ + const slot = useSlots() + return () => h('div', slot.default?.() ?? [ h(GroupItemComponent, { disabled: !!props.disabledItems?.[0] }), h(GroupItemComponent, { disabled: !!props.disabledItems?.[1] }), ]) @@ -370,5 +371,39 @@ describe('group', () => { expect(wrapper.emitted('update:modelValue')).toStrictEqual([[[0]]]) }) + + it('should update the items that use index as the value when delete', async () => { + const values = reactive(['one', 'two', 'three']) + const wrapper = mount(GroupComponent, { + props: { + multiple: false, + mandatory: false, + }, + slots: { + default () { + return values.map(value => h(GroupItemComponent, { key: value })) + }, + }, + }) + values.splice(1, 1) + values.push('four') + await nextTick() + let items = wrapper.findAllComponents(GroupItemComponent) + + await items[1].trigger('click') + await items[2].trigger('click') + + expect(wrapper.emitted()['update:modelValue']).toEqual([[1], [2]]) + + values.splice(1, 0, 'eight') + values.push('nine') + await nextTick() + items = wrapper.findAllComponents(GroupItemComponent) + + await items[3].trigger('click') + await items[4].trigger('click') + + expect(wrapper.emitted()['update:modelValue']).toEqual([[1], [2], [3], [4]]) + }) }) }) diff --git a/packages/vuetify/src/composables/group.ts b/packages/vuetify/src/composables/group.ts index 318f127f298..42d7e6b14a5 100644 --- a/packages/vuetify/src/composables/group.ts +++ b/packages/vuetify/src/composables/group.ts @@ -2,7 +2,7 @@ import { useProxiedModel } from './proxiedModel' // Utilities -import { computed, inject, onBeforeUnmount, onMounted, provide, reactive, toRef, unref, watch } from 'vue' +import { computed, inject, onBeforeUnmount, onMounted, onUpdated, provide, reactive, toRef, unref, watch } from 'vue' import { consoleWarn, deepEqual, findChildrenWithProvide, getCurrentInstance, getUid, propsFactory, wrapInArray } from '@/util' // Types @@ -13,6 +13,7 @@ export interface GroupItem { id: number value: Ref disabled: Ref + useIndexAsValue?: boolean } export interface GroupProps { @@ -181,6 +182,7 @@ export function useGroup ( if (unref(unwrapped.value) == null) { unwrapped.value = index + unwrapped.useIndexAsValue = true } if (index > -1) { @@ -219,6 +221,15 @@ export function useGroup ( isUnmounted = true }) + onUpdated(() => { + // #19655 update the items that use the index as the value. + for (let i = 0; i < items.length; i++) { + if (items[i].useIndexAsValue) { + items[i].value = i + } + } + }) + function select (id: number, value?: boolean) { const item = items.find(item => item.id === id) if (value && item?.disabled) return