AutoComplete
Import
import { AutoComplete } from '@pzeta/vue-components'
Esempio Base
<script setup lang="ts">
import { ref } from 'vue'
const selectedCountry = ref(null)
const suggestions = ref<string[]>([])
const allCountries = ['Italia', 'Francia', 'Germania', 'Spagna', 'Portogallo']
function search(event: { query: string }) {
const query = event.query.toLowerCase()
suggestions.value = allCountries.filter(c => c.toLowerCase().includes(query))
}
</script>
<template>
<AutoComplete
v-model="selectedCountry"
:suggestions="suggestions"
placeholder="Cerca un paese..."
label="Paese"
@complete="search"
/>
</template>
Come funziona l'evento complete
L'evento complete viene emesso ogni volta che l'utente digita nel campo (dopo il delay configurato e con almeno minLength caratteri). Il gestore deve popolare la prop :suggestions con i risultati filtrati. Il componente non filtra autonomamente — la logica di ricerca è completamente a carico del consumatore (locale o API remota).
function search(event: { originalEvent: Event; query: string }) {
// Filtraggio locale
suggestions.value = allItems.filter(item =>
item.toLowerCase().includes(event.query.toLowerCase())
)
// Oppure chiamata API
// suggestions.value = await api.search(event.query)
}
Props
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
modelValue | T | T[] | null | — | Valore corrente (v-model) |
suggestions | T[] | null | Array di suggerimenti da visualizzare nel dropdown |
optionLabel | string | ((item: T) => string) | null | Campo da usare come label quando T è un oggetto |
optionValue | string | ((item: T) => unknown) | null | Campo per il valore quando T è un oggetto |
optionDisabled | string | ((item: T) => boolean) | null | Campo per disabilitare opzioni |
optionGroupLabel | string | ((group: T) => string) | null | Label gruppo opzioni |
optionGroupChildren | string | ((group: T) => T[]) | null | Children gruppo opzioni |
dataKey | string | null | Campo univoco per tracking |
placeholder | string | null | Placeholder dell'input |
multiple | boolean | false | Abilita selezione multipla (chips) |
typeahead | boolean | true | Abilita typeahead in modalità multiple |
dropdown | boolean | false | Mostra pulsante dropdown per aprire il pannello |
dropdownMode | 'blank' | 'current' | 'blank' | Modalità del dropdown button: blank=ricerca vuota, current=ricerca con testo corrente |
minLength | number | 1 | Numero minimo di caratteri per attivare la ricerca |
delay | number | 300 | Delay in ms prima di emettere l'evento complete |
completeOnFocus | boolean | false | Emette complete al focus (mostra tutti i suggerimenti) |
forceSelection | boolean | false | Forza la selezione da lista (svuota input se non selezionato) |
autoHighlight | boolean | true | Evidenzia automaticamente il primo suggerimento |
showClear | boolean | false | Mostra pulsante per azzerare la selezione |
label | string | null | Label mostrata sopra il campo |
helperText | string | null | Testo di aiuto sotto il campo |
error | string | null | Messaggio di errore |
invalid | boolean | false | Stato di validazione invalido |
disabled | boolean | false | Disabilita il componente |
readonly | boolean | false | Campo in sola lettura |
required | boolean | false | Campo obbligatorio |
fluid | boolean | false | Occupa tutta la larghezza disponibile |
size | 'small' | 'medium' | 'large' | 'medium' | Dimensione del componente |
variant | 'outlined' | 'filled' | 'outlined' | Variante visiva |
severity | Severity | 'primary' | Colore tema |
loading | boolean | false | Stato di caricamento |
scrollHeight | string | '200px' | Altezza massima del dropdown |
appendTo | 'body' | 'self' | 'body' | Target Teleport del dropdown |
inputId | string | null | ID dell'input per accessibilità |
inputClass | string | null | Classe CSS aggiuntiva per l'input |
inputStyle | string | Record<string, string | number> | null | Stile inline per l'input |
name | string | null | Nome per i form nativi |
ariaLabel | string | null | Aria label per screen reader |
ariaLabelledby | string | null | ID dell'elemento label ARIA |
selectOnFocus | boolean | false | Seleziona il testo all'input al focus |
autofocus | boolean | false | Focus automatico al mount |
virtualScrollerOptions | Record<string, unknown> | null | Opzioni per virtual scroller |
Emits
| Evento | Payload | Descrizione |
|---|---|---|
update:modelValue | T | T[] | null | Aggiornamento v-model |
complete | { originalEvent: Event, query: string } | Emesso quando l'utente digita — popolare suggestions in risposta |
itemSelect | { originalEvent: Event, value: T } | Selezione di un suggerimento |
itemUnselect | { originalEvent: Event, value: T } | Deselezione in modalità multipla |
dropdownClick | { originalEvent: Event, query: string } | Click sul pulsante dropdown |
change | { originalEvent: Event, value: T | T[] | null } | Cambio valore |
clear | Event | Selezione azzerata |
focus | FocusEvent | Il componente riceve il focus |
blur | FocusEvent | Il componente perde il focus |
keydown | KeyboardEvent | Pressione tasto |
beforeShow | — | Prima dell'apertura del dropdown |
show | — | Dropdown aperto |
beforeHide | — | Prima della chiusura del dropdown |
hide | — | Dropdown chiuso |
Slot
| Slot | Scope | Descrizione |
|---|---|---|
option | { option: T, index: number } | Template per ogni singola opzione |
optiongroup | { option: T } | Template per l'intestazione del gruppo |
header | — | Contenuto in cima al dropdown |
footer | — | Contenuto in fondo al dropdown |
empty | — | Messaggio quando non ci sono suggerimenti |
chip | { value: T } | Template per ogni chip in modalità multipla |
dropdownicon | — | Icona del dropdown button personalizzata |
loadingicon | — | Icona di caricamento personalizzata |
clearicon | — | Icona del pulsante clear personalizzata |
removetokenicon | — | Icona di rimozione chip personalizzata |
Esempi
Selezione multipla (tags)
In modalità multipla il v-model è un array. I valori selezionati vengono mostrati come chips nell'input. Premendo Backspace con l'input vuoto rimuove l'ultimo chip:
<script setup lang="ts">
const selectedTags = ref<string[]>([])
const tags = ref<string[]>([])
const allTags = ['Vue.js', 'React', 'Angular', 'TypeScript', 'Node.js']
function search(event: { query: string }) {
tags.value = allTags.filter(t =>
t.toLowerCase().includes(event.query.toLowerCase()) &&
!selectedTags.value.includes(t)
)
}
</script>
<template>
<AutoComplete
v-model="selectedTags"
:suggestions="tags"
:multiple="true"
placeholder="Aggiungi tag..."
label="Linguaggi e Framework"
@complete="search"
/>
</template>
Con oggetti tipizzati
<script setup lang="ts">
interface Country { code: string; name: string }
const selected = ref<Country | null>(null)
const suggestions = ref<Country[]>([])
const allCountries: Country[] = [
{ code: 'IT', name: 'Italia' },
{ code: 'FR', name: 'Francia' },
]
function search(event: { query: string }) {
suggestions.value = allCountries.filter(c =>
c.name.toLowerCase().includes(event.query.toLowerCase())
)
}
</script>
<template>
<AutoComplete
v-model="selected"
:suggestions="suggestions"
option-label="name"
data-key="code"
@complete="search"
/>
</template>
Con dropdown button
<AutoComplete
v-model="selected"
:suggestions="suggestions"
dropdown
dropdown-mode="blank"
@complete="search"
@dropdown-click="loadAll"
/>
completeOnFocus — mostra tutto al focus
<AutoComplete
v-model="selected"
:suggestions="suggestions"
:complete-on-focus="true"
:min-length="0"
@complete="search"
/>
forceSelection — obbliga selezione dalla lista
Se l'utente digita qualcosa e poi esce senza selezionare, il campo viene svuotato:
<AutoComplete
v-model="selected"
:suggestions="suggestions"
:force-selection="true"
@complete="search"
/>
Slot option personalizzato
<AutoComplete v-model="selected" :suggestions="countries" option-label="name" @complete="search">
<template #option="{ option }">
<div class="flex items-center gap-2">
<img :src="`/flags/${option.code}.svg`" class="w-6 h-4" />
<span>{{ option.name }}</span>
</div>
</template>
</AutoComplete>
Stati
<AutoComplete :suggestions="[]" label="Disabilitato" disabled @complete="() => {}" />
<AutoComplete :suggestions="[]" label="Caricamento" loading @complete="() => {}" />
<AutoComplete
v-model="val"
:suggestions="[]"
label="Errore"
error="Campo obbligatorio"
invalid
@complete="() => {}"
/>
Accessibilità
- L'input è un elemento
<input type="text">nativo conautocomplete="off" - Supporto navigazione tastiera:
ArrowDown/Upnaviga i suggerimenti,Enterseleziona,Escapechiude,Tabchiude il pannello - In modalità multipla
Backspacecon input vuoto rimuove l'ultimo chip aria-labelearia-labelledbypropagati all'input nativo
TypeScript
import type { AutoCompleteProps, AutoCompleteEmits, AutoCompleteCompleteEvent } from '@pzeta/vue-components'
function onComplete(event: AutoCompleteCompleteEvent) {
// event.query contiene il testo digitato
suggestions.value = filter(event.query)
}
Buttons
Componenti pulsante per azioni e interazioni UI — Button, ButtonGroup, SplitButton, ToggleButton, SelectButton, SpeedDial.
Calendar
Calendario inline standalone per la selezione di date in modalita singola, multipla o intervallo. Non include input testuale — usare DatePicker per il pattern input+popup.