Skip to content

Commit 28bcb88

Browse files
committed
fix: use object id in trackBy if key is object
1 parent 16459e2 commit 28bcb88

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

packages/ui/src/components/va-select/VaSelect.stories.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,27 @@ export const OptionMultipleAutocompleteContentSlot: StoryFn = () => ({
372372
</template>
373373
</VaSelect>`,
374374
})
375+
376+
export const EmptyTrackByLongList = defineStory({
377+
story: () => ({
378+
components: { VaSelect },
379+
380+
data () {
381+
return {
382+
value: '',
383+
options: Array.from({ length: 100 }, (_, i) => ({ text: `Option ${i + 1}`, value: i + 1 })),
384+
}
385+
},
386+
387+
template: `
388+
<VaSelect v-model="value" :options="options" placeholder="Select an option" />
389+
`,
390+
}),
391+
392+
async tests ({ canvasElement, step, expect }) {
393+
step('Expect no error when mounted', () => {
394+
const error = canvasElement.querySelector('.va-input-wrapper.va-input-wrapper--error') as HTMLElement
395+
expect(error).toBeNull()
396+
})
397+
},
398+
})

packages/ui/src/composables/tests/useSelectableList.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe('useSelectableList', () => {
5454
{
5555
getGroupBy: undefined,
5656
getText: 'textValue',
57-
getTrackBy: { text: 'textValue', disabled: false },
57+
getTrackBy: 'va-obj-id-2',
5858
getValue: { text: 'textValue', disabled: false },
5959
getDisabled: false,
6060
},

packages/ui/src/composables/useSelectableList.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { ExtractPropTypes, PropType } from 'vue'
22

33
import { getValueByKey } from '../utils/value-by-key'
44
import { isObject } from '../utils/is-object'
5+
import { getObjectId } from '../utils/get-object-uid'
56

67
export type SelectableOption = string | number | boolean | Record<string, any> | null | undefined
78
export type StringOrFunction = string | ((option: SelectableOption) => unknown)
@@ -35,7 +36,13 @@ export function useSelectableList (props: ExtractPropTypes<typeof useSelectableL
3536
}
3637

3738
const getTrackBy = (option: SelectableOption): string | number => {
38-
return props.trackBy ? getOptionProperty(option, props.trackBy) : getValue(option)
39+
const key = props.trackBy ? getOptionProperty(option, props.trackBy) : getValue(option)
40+
41+
if (typeof key === 'object') {
42+
return getObjectId(key)
43+
}
44+
45+
return key
3946
}
4047

4148
const getDisabled = (option: SelectableOption): boolean => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
let count: number = 1
2+
3+
const idMap = new WeakMap<Record<string, unknown>, string>()
4+
5+
export function getObjectId (object: Record<string, unknown>): string {
6+
const objectId = idMap.get(object)
7+
8+
if (objectId === undefined) {
9+
count += 1
10+
const key = `va-obj-id-${count}`
11+
idMap.set(object, key)
12+
13+
return key
14+
}
15+
16+
return objectId
17+
}

0 commit comments

Comments
 (0)