Skip to content

Commit 408a95d

Browse files
authored
fix(VCombobox): select all values from pasted text (#21840)
resolves #21838
1 parent 5e3fc2b commit 408a95d

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

packages/vuetify/src/components/VCombobox/VCombobox.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
checkPrintable,
3333
deepEqual,
3434
ensureValidVNode,
35+
escapeForRegex,
3536
genericComponent,
3637
IN_BROWSER,
3738
isComposingIgnoreKey,
@@ -153,20 +154,24 @@ export const VCombobox = genericComponent<new <
153154
get: () => {
154155
return _search.value
155156
},
156-
set: (val: string | null) => {
157+
set: async (val: string | null) => {
157158
_search.value = val ?? ''
158159
if (!props.multiple && !hasSelectionSlot.value) {
159160
model.value = [transformItem(props, val)]
160161
nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0))
161162
}
162163

163164
if (val && props.multiple && props.delimiters?.length) {
164-
const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`))
165+
const signsToMatch = props.delimiters.map(escapeForRegex).join('|')
166+
const values = val.split(new RegExp(`(?:${signsToMatch})+`))
165167
if (values.length > 1) {
166-
values.forEach(v => {
168+
for (let v of values) {
167169
v = v.trim()
168-
if (v) select(transformItem(props, v))
169-
})
170+
if (v) {
171+
select(transformItem(props, v))
172+
await nextTick()
173+
}
174+
}
170175
_search.value = ''
171176
}
172177
}

packages/vuetify/src/components/VCombobox/__tests__/VCombobox.spec.browser.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,25 @@ describe('VCombobox', () => {
746746
expect(onFocus).toHaveBeenCalledTimes(1)
747747
})
748748

749+
it.each([
750+
{ delimiters: [','], text: 'abc,foo, baz', expected: ['abc', 'foo', 'baz'] },
751+
{ delimiters: [':'], text: '012:2,32:0:1', expected: ['012', '2,32', '0', '1'] },
752+
{ delimiters: [':', '.', '-'], text: '(1) 231:13 - 123.', expected: ['(1) 231', '13', '123'] },
753+
])('should ingest new items when a delimited text is pasted', async ({ delimiters, text, expected }) => {
754+
const model = ref(null)
755+
render(() => (
756+
<VCombobox
757+
v-model={ model.value }
758+
delimiters={ delimiters }
759+
multiple
760+
/>
761+
))
762+
await userEvent.tab()
763+
navigator.clipboard.writeText(text)
764+
await userEvent.paste()
765+
expect(model.value).toEqual(expected)
766+
})
767+
749768
describe('Showcase', () => {
750769
generate({ stories })
751770
})

0 commit comments

Comments
 (0)