Components
SelectRemote
Dropdown con caricamento opzioni da sorgente remota, filtri dinamici e template personalizzabile.
Panoramica
SelectRemote è un componente dropdown che carica le opzioni in modo asincrono tramite una fetchFn. Supporta filtri dinamici basati su altri campi del form, template personalizzati per le etichette e immagini nelle opzioni.
Caratteristiche principali:
- Caricamento asincrono opzioni tramite
fetchFn - Filtri dinamici: quando i valori di altri campi cambiano, i dati vengono ricaricati automaticamente (
filterFields+fullData) - Template etichette con interpolazione (
optionTemplate) - Immagini nelle opzioni (
optionImage) - Ricerca/filtro integrato
Casi d'uso tipici: selezione categorie, comuni/province, utenti, prodotti, qualsiasi lookup su API.
Anteprima live (con fetchFn mockato)
Nel preview qui sotto la fetchFn simula una chiamata API ritornando un array statico — in produzione la stessa funzione effettua un fetch() verso il backend.
Pattern fetchFn
type FetchFn<T = Record<string, unknown>> = (
filters?: FilterCriteria,
signal?: AbortSignal
) => Promise<T[]>
// Esempio base
const fetchCategorie = async () => {
const res = await fetch('/api/categorie')
return res.json()
}
// Con filtri passati dal composable
const fetchComuni = async (filters?: FilterCriteria) => {
const params = new URLSearchParams()
if (filters?.provinciaId) params.set('provinciaId', String(filters.provinciaId.value))
const res = await fetch(`/api/comuni?${params}`)
return res.json()
}
Utilizzo nello schema
const schema = [{
name: 'idCategoria',
type: 'selectremote',
label: 'Categoria',
props: {
fetchFn: fetchCategorie,
optionLabel: 'nome',
optionValue: 'id',
showFilter: true,
showClear: true,
}
}, {
// Filtro dinamico: ricarica comuni quando cambia la provincia
name: 'idComune',
type: 'selectremote',
label: 'Comune',
props: {
fetchFn: fetchComuni,
optionLabel: 'nome',
optionValue: 'id',
filterFields: ['idProvincia'], // Osserva questo campo
// fullData viene iniettato automaticamente da DynamicFormLayouts
}
}, {
// Con template personalizzato per etichetta
name: 'idUtente',
type: 'selectremote',
label: 'Assegna a',
props: {
fetchFn: fetchUtenti,
optionTemplate: '{cognome} {nome} ({email})',
optionValue: 'id',
}
}]
Utilizzo diretto
<SelectRemote
v-model="idSelezionato"
:fetch-fn="fetchCategorie"
option-label="nome"
option-value="id"
label="Categoria"
show-filter
show-clear
/>
Con filtro dinamico (fuori DynamicFormLayouts)
<SelectRemote
v-model="idComune"
:fetch-fn="fetchComuni"
option-label="nome"
option-value="id"
:filter-fields="['idProvincia']"
:full-data="formData"
label="Comune"
/>
Con immagini nelle opzioni
<SelectRemote
v-model="idPaese"
:fetch-fn="fetchPaesi"
option-label="nome"
option-value="codice"
option-image="urlBandiera"
label="Paese"
/>
Props
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
modelValue | string | number | boolean | null | null | Valore selezionato (v-model) |
label | string | — | Etichetta del campo |
helperText | string | — | Testo di supporto sotto il campo |
error | string | — | Messaggio di errore (attiva stato invalid) |
disabled | boolean | false | Disabilita il campo |
invalid | boolean | false | Attiva visivamente lo stato di errore |
required | boolean | false | Indica campo obbligatorio |
fetchFn | FetchFn | — | Funzione asincrona per caricare le opzioni |
filter | string | FilterCriteria | — | Filtro statico passato alla fetchFn |
filterFields | string[] | [] | Campi del form da osservare per filtri dinamici |
fullData | Record<string, unknown> | {} | Dati completi del form (per filtri dinamici) |
optionLabel | string | 'label' | Proprietà dell'oggetto da usare come etichetta |
optionTemplate | string | — | Template interpolato per l'etichetta, es. '{nome} ({codice})' |
optionValue | string | 'value' | Proprietà dell'oggetto da usare come valore |
optionImage | string | — | Proprietà dell'oggetto contenente URL immagine |
showClear | boolean | false | Mostra pulsante per resettare la selezione |
showFilter | boolean | false | Abilita ricerca nel dropdown |
filterPlaceholder | string | (da i18n) | Placeholder del campo di ricerca |
Metodi esposti
| Metodo | Descrizione |
|---|---|
reload() | Ricarica i dati chiamando nuovamente la fetchFn |
<SelectRemote ref="selectRef" :fetch-fn="fetchCategorie" ... />
// Nel codice
selectRef.value?.reload()
Eventi
| Evento | Payload | Descrizione |
|---|---|---|
update:modelValue | string | number | boolean | null | Valore aggiornato |
Validazione suggerita
import { z } from 'zod'
const schema = z.object({
idCategoria: z.number({ required_error: 'Seleziona una categoria' })
.positive('ID categoria non valido')
.nullable()
.refine(v => v !== null, { message: 'La categoria è obbligatoria' }),
})