Forms

AutoComplete

Campo di input con suggerimenti automatici caricati dinamicamente tramite l'evento complete. Supporta selezione singola e multipla (chips), dropdown button e forceSelection.

Import

import { AutoComplete } from '@pzeta/vue-components'

Esempio Base

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

PropTipoDefaultDescrizione
modelValueT | T[] | null—Valore corrente (v-model)
suggestionsT[]nullArray di suggerimenti da visualizzare nel dropdown
optionLabelstring | ((item: T) => string)nullCampo da usare come label quando T è un oggetto
optionValuestring | ((item: T) => unknown)nullCampo per il valore quando T è un oggetto
optionDisabledstring | ((item: T) => boolean)nullCampo per disabilitare opzioni
optionGroupLabelstring | ((group: T) => string)nullLabel gruppo opzioni — grouping non ancora implementato: i suggerimenti sono sempre flat
optionGroupChildrenstring | ((group: T) => T[])nullChildren gruppo opzioni — grouping non ancora implementato
dataKeystringnullCampo univoco per tracking
placeholderstringnullPlaceholder dell'input
multiplebooleanfalseAbilita selezione multipla (chips)
typeaheadbooleantrueAbilita typeahead in modalità multiple
dropdownbooleanfalseMostra pulsante dropdown per aprire il pannello
dropdownMode'blank' | 'current''blank'Modalità del dropdown button: blank=ricerca vuota, current=ricerca con testo corrente
minLengthnumber1Numero minimo di caratteri per attivare la ricerca
delaynumber300Delay in ms prima di emettere l'evento complete
completeOnFocusbooleanfalseEmette complete al focus (mostra tutti i suggerimenti)
forceSelectionbooleanfalseForza la selezione da lista (svuota input se non selezionato)
allowCreateOnEnterbooleanfalseConsente di creare un valore da testo libero premendo Enter (solo multiple con forceSelection=false); emette createNew e aggiunge la stringa al v-model
autoHighlightbooleantrueEvidenzia automaticamente il primo suggerimento
showClearbooleanfalseMostra pulsante per azzerare la selezione
labelstringnullLabel mostrata sopra il campo
helperTextstringnullTesto di aiuto sotto il campo
errorstringnullMessaggio di errore
reserveMessageSpacebooleantrueRiserva sotto il campo lo spazio del messaggio anche senza helperText né error, così un errore non sposta i campi sotto. false nelle barre filtri: un error resta comunque visibile (dalla 1.23.0)
invalidbooleanfalseStato di validazione invalido
disabledbooleanfalseDisabilita il componente
readonlybooleanfalseCampo in sola lettura
requiredbooleanfalseCampo obbligatorio
fluidbooleanfalseOccupa tutta la larghezza disponibile
size'small' | 'medium' | 'large''medium'Dimensione del componente
variant'outlined' | 'filled''outlined'Variante visiva
severitySeverity'primary'Colore tema
loadingbooleanfalseStato di caricamento
scrollHeightstring'200px'Altezza massima del dropdown
appendTo'body' | 'self''body'Target Teleport del dropdown
inputIdstringnullID dell'input per accessibilità
inputClassstringnullClasse CSS aggiuntiva per l'input
inputStylestring | Record<string, string | number>nullStile inline per l'input
namestringnullNome per i form nativi
ariaLabelstringnullAria label per screen reader
ariaLabelledbystringnullID dell'elemento label ARIA
selectOnFocusbooleanfalseSeleziona il testo all'input al focus
autofocusbooleanfalseFocus automatico al mount
virtualScrollerOptions{ itemSize?: number } | nullnullOpzioni per virtual scroller. Impostando itemSize (altezza in px di ogni opzione) si attiva la virtualizzazione (row windowing) della lista suggerimenti, riducendo i nodi DOM su liste molto lunghe

Emits

EventoPayloadDescrizione
update:modelValueT | T[] | nullAggiornamento v-model
complete{ originalEvent: Event, query: string, signal?: AbortSignal }Emesso quando l'utente digita — popolare suggestions in risposta. signal (AbortSignal) consente di annullare fetch obsolete: ogni nuova ricerca aborta la precedente
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
clearEventSelezione azzerata
focusFocusEventIl componente riceve il focus
blurFocusEventIl componente perde il focus
keydownKeyboardEventPressione tasto
createNew{ originalEvent: KeyboardEvent, query: string }Emesso in modalità multipla con allowCreateOnEnter quando si preme Enter su testo libero non presente nella lista
beforeShow—Prima dell'apertura del dropdown
show—Dropdown aperto
beforeHide—Prima della chiusura del dropdown
hide—Dropdown chiuso

Slot

SlotScopeDescrizione
option{ option: T, index: number }Template per ogni singola opzione
optiongroup{ option: T }Template per l'intestazione del gruppo — grouping non ancora implementato, lo slot non viene renderizzato
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:

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

Accessibilità

  • L'input è un elemento <input type="text"> nativo con autocomplete="off"
  • Supporto navigazione tastiera: ArrowDown/Up naviga i suggerimenti, Enter seleziona, Escape chiude, Tab chiude il pannello
  • In un Dialog, Escape a pannello aperto chiude solo il pannello, anche col focus fuori dal campo (useEscapeWhileOpen, dalla 1.24.0)
  • In modalità multipla Backspace con input vuoto rimuove l'ultimo chip
  • aria-label e aria-labelledby propagati 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)
}