Last active
February 6, 2025 20:18
-
-
Save InToSSH/d4a3b21fc86dd0b54b6ee4559378bc22 to your computer and use it in GitHub Desktop.
PrimeVue AutoComplete wrapper to accept array of objects for items with 'label' and 'value' props and return only the 'value' prop value in the v-model. It now also supports the multiple version - return an array of values (IDs) and also accepts array of values as v-model and converts them back to objects for the OG Autocomplete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="field"> | |
<label :for="id" :class="{'p-error':(v && v.$invalid && v.$dirty)}">{{ label }} {{ v && 'required' in v ? '*' : ''}}</label> | |
<AutoComplete | |
:model-value="modelItem" | |
@update:modelValue="(selected) => valueUpdated(selected)" | |
:suggestions="filteredItems" | |
@complete="searchItems($event)" | |
:dropdown="true" | |
:multiple="multiple" | |
optionLabel="label" | |
forceSelection | |
input-class="p-inputtext-sm w-full" | |
class="p-inputtext-sm w-full " | |
> | |
</AutoComplete> | |
<small v-if="(v && v.$invalid && v.$dirty)" class="p-error">{{v.$errors[0].$message.replace('Value', label)}}</small> | |
</div> | |
</template> | |
<style scoped> | |
label { | |
display: block !important; | |
} | |
.p-autocomplete:deep(.p-button-icon-only) { | |
padding: 0.3rem 0; | |
} | |
.field { | |
margin-bottom: 0.25rem; | |
} | |
.p-autocomplete:deep(.p-autocomplete-multiple-container) { | |
width: 100%; | |
} | |
</style> | |
<script setup> | |
import {computed, ref, defineEmits} from 'vue'; | |
import AutoComplete from "primevue/autocomplete"; | |
const emit = defineEmits(['update:modelValue']); | |
const props = defineProps([ | |
'id', | |
'label', | |
'modelValue', | |
'items', | |
'v', | |
'multiple', | |
]) | |
const modelItem = computed(() => { | |
if (props.multiple) { | |
if (props.modelValue && props.modelValue.length) { | |
return props.items.filter(item => props.modelValue.includes(item.value)); | |
} | |
return []; | |
} | |
return props.items.find(item => item.value == props.modelValue) ?? props.modelValue; | |
}) | |
const filteredItems = ref(); | |
const searchItems = (event) => { | |
setTimeout(() => { | |
if (!event.query.trim().length) { | |
filteredItems.value = [...props.items]; | |
} | |
else { | |
filteredItems.value = props.items.filter((item) => { | |
return item.label.toLowerCase().startsWith(event.query.toLowerCase()); | |
}); | |
} | |
}, 100); | |
}; | |
const valueUpdated = (selected) => { | |
if (selected && typeof selected === 'object' && 'value' in selected) { | |
emit('update:modelValue', selected.value); | |
} else if (props.multiple && selected && selected.length && selected[0].hasOwnProperty('value')) { | |
let selectedIds = selected.flatMap(i => i.value); | |
emit('update:modelValue', selectedIds); | |
} else { | |
console.log('skocili jsme sem', typeof selected); | |
emit('update:modelValue', selected ); | |
} | |
} | |
</script> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment