Skip to content

Commit 2de6dca

Browse files
committed
feat(PrimeAutoComplete): default use commas as separator on paste, add support for multiple custom separators in paste handling,
1 parent 493566e commit 2de6dca

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

dev/pages/inputs/AutoComplete.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ const schema
5555
typeahead: false,
5656
label: 'Chips Replacement',
5757
},
58+
{
59+
$formkit: 'primeAutoComplete',
60+
id: 'chips',
61+
name: 'chips',
62+
multiple: true,
63+
typeahead: false,
64+
label: 'Chips - Paste separated values by comma or semicolon',
65+
separators: [',', ';'],
66+
},
5867
]
5968
6069
const data = { id: { id: '1', name: 'Tom', value: '123' } }

src/components/PrimeAutoComplete.vue

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface FormKitPrimeAutoCompleteProps {
1919
minLength?: AutoCompleteProps['minLength']
2020
placeholder?: AutoCompleteProps['placeholder']
2121
fluid?: AutoCompleteProps['fluid']
22+
separators?: string[] | []
2223
}
2324
2425
const props = defineProps({
@@ -34,6 +35,12 @@ const suggestions = ref(['', {}])
3435
suggestions.value = []
3536
const loading = ref(false)
3637
38+
/**
39+
* Searches for suggestions based on the input query.
40+
* If options and optionLabel are provided, it filters the options.
41+
* Otherwise, it calls the complete function from the context to fetch suggestions.
42+
* @param event - The AutoCompleteCompleteEvent containing the query.
43+
*/
3744
async function search(event: AutoCompleteCompleteEvent) {
3845
if (props.context?.options && props.context?.optionLabel) {
3946
suggestions.value = props.context.options.filter((option) => {
@@ -54,6 +61,38 @@ async function search(event: AutoCompleteCompleteEvent) {
5461
}
5562
}
5663
}
64+
65+
/**
66+
* Handles paste event to transform a string separated by any of the provided separators into multiple items.
67+
* @param event - The paste event from the input.
68+
*/
69+
function handlePaste(event: ClipboardEvent) {
70+
if (!props.context?.multiple)
71+
return
72+
const clipboardData = event.clipboardData
73+
if (!clipboardData)
74+
return
75+
const pastedText = clipboardData.getData('text')
76+
const separators = Array.isArray(props.context?.separators) && props.context.separators.length > 0
77+
? props.context.separators
78+
: [',']
79+
// Create a regex to split by any separator, escaping special regex characters
80+
const regex = new RegExp(`[${separators.map(s => s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')).join('')}]`)
81+
if (pastedText && regex.test(pastedText)) {
82+
event.preventDefault()
83+
const items = pastedText
84+
.split(regex)
85+
.map(item => item.trim())
86+
.filter(item => item.length > 0)
87+
if (Array.isArray(props.context._value)) {
88+
props.context._value.push(...items)
89+
}
90+
else {
91+
props.context._value = items
92+
}
93+
props.context?.node?.input?.(props.context?._value)
94+
}
95+
}
5796
</script>
5897

5998
<template>
@@ -85,6 +124,7 @@ async function search(event: AutoCompleteCompleteEvent) {
85124
@complete="search"
86125
@change="handleInput"
87126
@blur="handleBlur"
127+
@paste="handlePaste"
88128
>
89129
<template v-for="slotName in validSlotNames" :key="slotName" #[slotName]="slotProps">
90130
<component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />

src/definitions/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import PrimeToggleSwitch from '../components/PrimeToggleSwitch.vue'
2626
import PrimeTreeSelect from '../components/PrimeTreeSelect.vue'
2727

2828
export const primeAutoCompleteDefinition: FormKitTypeDefinition = createInput(PrimeAutoComplete, {
29-
props: ['pt', 'ptOptions', 'unstyled', 'Select', 'multiple', 'typeahead', 'optionLabel', 'options', 'size', 'minLength', 'placeholder', 'fluid'],
29+
props: ['pt', 'ptOptions', 'unstyled', 'Select', 'multiple', 'typeahead', 'optionLabel', 'options', 'size', 'minLength', 'placeholder', 'fluid', 'separators'],
3030
})
3131
export const primeInputTextDefinition: FormKitTypeDefinition = createInput(PrimeInputText, {
3232
props: ['pt', 'ptOptions', 'unstyled', 'placeholder', 'iconPrefix', 'iconSuffix', 'size', 'inputType'],

0 commit comments

Comments
 (0)