Components
TreeRemote
Componente Tree gerarchico con nodi caricati da sorgente remota, selezione singola, multipla o checkbox.
Panoramica
TreeRemote è un componente Tree che carica la struttura gerarchica dei nodi in modo asincrono tramite fetchFn. Ideale per dati con struttura ad albero come categorie, organigrammi, filesystem o menu di navigazione.
La fetchFn deve restituire un array di TreeNode nel formato PrimeVue:
interface TreeNode {
key: string
label: string
data?: unknown
icon?: string
children?: TreeNode[]
leaf?: boolean
}
Caratteristiche principali:
- Tre modalità di selezione:
single,multiple,checkbox - Filtro/ricerca sui nodi
- Filtri dinamici su altri campi del form
- Supporto
metaKeySelectionper selezione multipla con Ctrl/Cmd
Casi d'uso tipici: navigazione categorie, selezione reparti organizzativi, selezione voci di menu, strutture di classificazione.
Anteprima live (con fetchFn mockato)
Utilizzo nello schema
const schema = [{
name: 'categoriaSelezionata',
type: 'treeremote',
label: 'Categoria',
props: {
fetchFn: fetchAlberoCategorie,
selectionMode: 'single',
showFilter: true,
}
}, {
// Selezione multipla con checkbox
name: 'repartiAssegnati',
type: 'treeremote',
label: 'Reparti',
props: {
fetchFn: fetchAlberoReparti,
selectionMode: 'checkbox',
metaKeySelection: false,
}
}]
Utilizzo diretto
Selezione singola
<TreeRemote
v-model="categoriaSelezionata"
:fetch-fn="fetchCategorie"
selection-mode="single"
show-filter
label="Categoria"
/>
Selezione multipla con checkbox
<TreeRemote
v-model="repartiSelezionati"
:fetch-fn="fetchReparti"
selection-mode="checkbox"
:meta-key-selection="false"
label="Reparti assegnati"
/>
Struttura dati attesa da fetchFn
// La fetchFn deve restituire TreeNode[]
const fetchCategorie = async (): Promise<TreeNode[]> => {
const res = await fetch('/api/categorie/albero')
const data = await res.json()
// Trasformare i dati nel formato TreeNode se necessario
return data
}
// Esempio struttura TreeNode
const esempio: TreeNode[] = [{
key: '0',
label: 'Elettronica',
icon: 'pi pi-desktop',
children: [{
key: '0-0',
label: 'Computer',
icon: 'pi pi-laptop',
data: { id: 1, slug: 'computer' }
}, {
key: '0-1',
label: 'Smartphone',
icon: 'pi pi-mobile',
leaf: true,
data: { id: 2, slug: 'smartphone' }
}]
}]
Formato del valore (modelValue)
Il valore dipende dalla selectionMode:
// selectionMode: 'single'
// Record<string, boolean> con una sola chiave
{ '0-1': true }
// selectionMode: 'multiple'
// Record<string, boolean> con più chiavi
{ '0-0': true, '0-1': true }
// selectionMode: 'checkbox'
// Record con stato checked/partialChecked per ogni nodo
{ '0': { checked: false, partialChecked: true }, '0-0': { checked: true, partialChecked: false } }
Props
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
modelValue | Record<string, boolean> | string[] | null | null | Nodi selezionati (v-model). Record<string, boolean> per single/multiple/checkbox; string[] accettato come alternativa quando il consumer gestisce la selezione come lista di chiavi |
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 |
fetchFn | FetchFn<TreeNode> | — | Funzione asincrona per caricare i nodi |
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) |
selectionMode | 'single' | 'multiple' | 'checkbox' | 'single' | Modalità di selezione |
showFilter | boolean | false | Mostra campo di ricerca/filtro |
filterPlaceholder | string | (da i18n) | Placeholder del campo filtro |
metaKeySelection | boolean | true | Richiede Ctrl/Cmd per selezione multipla |
Metodi esposti
| Metodo | Descrizione |
|---|---|
reload() | Ricarica i nodi chiamando nuovamente la fetchFn |
Slot
Tutti gli slot del componente Tree di @pzeta/vue-components vengono propagati automaticamente. Slot tipici:
| Slot | Props | Descrizione |
|---|---|---|
default | { node } | Template personalizzato per ogni nodo (sostituisce label + icon) |
nodeicon | { node, expanded, selected } | Override dell'icona del nodo |
togglericon | { node, expanded } | Override dell'icona di espansione/collasso |
header/footer | — | Contenuto sopra/sotto la lista nodi |
Eventi
| Evento | Payload | Descrizione |
|---|---|---|
update:modelValue | Record<string, boolean> | string[] | null | Selezione aggiornata |
Validazione suggerita
import { z } from 'zod'
const schema = z.object({
// Selezione singola: verifica che almeno un nodo sia selezionato
categoriaSelezionata: z.record(z.boolean())
.refine(v => Object.keys(v).length > 0, 'Seleziona una categoria')
.nullable()
.refine(v => v !== null, { message: 'La categoria è obbligatoria' }),
})