Forms

Select

Dropdown di selezione singola o multipla con supporto a filtro, opzioni raggruppate e chips. Componente custom con navigazione tastiera e type-ahead integrati.

Import

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

Esempio Base

Opzioni: oggetti vs stringhe

Array di oggetti (caso tipico)

Specificare option-label e option-value per indicare quali proprietà usare come etichetta e valore:

<Select
  v-model="selected"
  :options="cities"
  option-label="name"
  option-value="id"
/>

Il v-model conterrà il valore della proprietà option-value (id nell'esempio sopra), non l'intero oggetto.

Array di stringhe

Se le opzioni sono stringhe primitive, omettere option-label e option-value:

<script setup lang="ts">
const options = ['Roma', 'Milano', 'Napoli']
const selected = ref(null)
</script>

<template>
  <Select v-model="selected" :options="options" placeholder="Seleziona..." />
</template>

Funzione come optionLabel

<Select
  v-model="selected"
  :options="users"
  :option-label="u => `${u.firstName} ${u.lastName}`"
  option-value="id"
/>

Props

PropTipoDefaultDescrizione
modelValueOptionValue | OptionValue[]nullValore selezionato (v-model)
optionsT[][]Array di opzioni
optionLabelstring | ((o: T) => string)nullProprietà o funzione per il testo visualizzato
optionValuestring | ((o: T) => OptionValue)nullProprietà o funzione per il valore
optionDisabledstring | ((o: T) => boolean)nullProprietà o funzione per opzione disabilitata
optionGroupLabelstring | ((o: T) => string)nullLabel del gruppo di opzioni
optionGroupChildrenstring | ((o: T) => unknown[])nullProprietà con le opzioni figlie di un gruppo
placeholderstringTesto quando nessuna opzione è selezionata
labelstringnullLabel mostrata sopra il campo
helperTextstringnullTesto di aiuto sotto il campo
errorstringnullMessaggio di errore
invalidbooleanfalseStato di validazione invalido
disabledbooleanfalseDisabilita il componente
readonlybooleanfalseCampo in sola lettura
requiredbooleanfalseCampo obbligatorio
multiplebooleanfalseAbilita selezione multipla con chips
filterbooleanfalseMostra campo di ricerca nel dropdown
filterMatchMode'startsWith' | 'contains' | 'endsWith''contains'Modalità di matching del filtro
filterPlaceholderstringPlaceholder del campo filtro
filterFieldsstring[]nullCampi su cui applicare il filtro
showClearbooleanfalseMostra pulsante per azzerare la selezione
checkmarkbooleanfalseMostra checkmark accanto all'opzione selezionata (single)
editablebooleanPermette di digitare testo libero oltre alle opzioni
fluidbooleantrueOccupa 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'14rem'Altezza massima del dropdown
appendTo'body' | 'self''body'Target Teleport del dropdown
dataKeystringnullChiave univoca per le opzioni (confronto oggetti)
inputIdstringnullID dell'input per accessibilità
namestringnullNome per i form nativi
ariaLabelstringnullAria label per screen reader
ariaLabelledbystringnullID dell'elemento label ARIA
autoFilterFocusbooleanfalseFocus automatico sul filtro all'apertura
resetFilterOnHidebooleanfalseResetta il filtro alla chiusura del dropdown
highlightOnSelectbooleantrueEvidenzia l'opzione selezionata nella lista
focusOnHoverbooleantrueSposta il focus all'opzione al passaggio del mouse
autoOptionFocusbooleantrueSposta il focus sulla prima opzione all'apertura
defaultValueOptionValue | OptionValue[]nullValore predefinito se modelValue non è fornito
visibleOptionsnumberNumero di opzioni visibili senza scroll
loadingIconstringClasse CSS icona di caricamento
clearIconstringClasse CSS icona di cancellazione
dropdownIconstringClasse CSS icona dropdown

Emits

EventoPayloadDescrizione
update:modelValueOptionValue | OptionValue[]Aggiornamento v-model
change{ originalEvent: Event, value: OptionValue | OptionValue[], selectedOption: T | T[] | null }Cambio di selezione con dettagli completi
filter{ originalEvent: Event, value: string }Cambio del testo filtro
clearEventSelezione azzerata
focusEventIl componente riceve il focus
blurEventIl componente perde il focus
keydownKeyboardEventPressione tasto
keyupKeyboardEventRilascio tasto
beforeShowPrima dell'apertura del dropdown
showDropdown aperto
beforeHidePrima della chiusura del dropdown
hideDropdown chiuso

Slot

SlotScopeDescrizione
value{ value, placeholder }Personalizza la visualizzazione del valore selezionato
option{ option, selected, index }Template per ogni singola opzione
optiongroup{ option }Template per l'intestazione del gruppo
headerContenuto in cima al dropdown
footerContenuto in fondo al dropdown
content{ options, value, selectOption }Override completo del contenuto del dropdown
emptyMessaggio quando non ci sono opzioni
emptyfilterMessaggio quando il filtro non produce risultati
loaderStato di caricamento nel dropdown
loadingiconIcona di caricamento personalizzata
cleariconIcona del pulsante clear personalizzata
dropdownicon{ expanded: boolean }Icona del dropdown personalizzata

Esempi

Con filtro di ricerca

Selezione multipla

In modalità multipla il v-model è un array di valori. Le opzioni selezionate vengono mostrate come chips rimuovibili nel trigger:

Opzioni raggruppate

Varianti e dimensioni

Con pulsante clear

Stati

Slot option personalizzato

<Select v-model="selected" :options="countries" option-label="name" option-value="code">
  <template #option="{ option, selected }">
    <span class="flex items-center gap-2">
      <img :src="`/flags/${option.code}.png`" class="w-5 h-4" />
      <span>{{ option.name }}</span>
      <span v-if="selected" class="ml-auto text-primary-600">✓</span>
    </span>
  </template>
</Select>

Evento change con dettagli completi

<Select
  v-model="selected"
  :options="cities"
  option-label="name"
  option-value="id"
  @change="({ value, selectedOption }) => console.log(value, selectedOption)"
/>

Accessibilità

  • Il trigger ha role="combobox" con aria-expanded e aria-haspopup
  • Supporto navigazione tastiera: ArrowDown/Up naviga le opzioni, Enter/Space seleziona, Escape chiude
  • Type-ahead: digitando una lettera naviga direttamente all'opzione corrispondente (con dropdown chiuso seleziona direttamente)
  • Input nascosto associato alla label tramite id per compatibilità con form nativi
  • aria-label e aria-labelledby configurabili
  • Ogni opzione ha role="option" e aria-selected
  • Il trigger è escluso dal tab order quando disabled

TypeScript

import type { SelectProps, SelectEmits } from '@pzeta/vue-components'

// Uso tipizzato
const cities: Array<{ id: number; name: string }> = [
  { id: 1, name: 'Roma' },
  { id: 2, name: 'Milano' },
]

const selected = ref<number | null>(null)