DataTable
Import
import { DataTable, Column } from '@pzeta/vue-components'
import type {
DataTableProps,
DataTableEmits,
DataTableFilterMeta,
DataTableSortMeta,
ColumnProps,
} from '@pzeta/vue-components'
Esempio Base
Props — DataTable
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
value | T[] | [] | Array di dati da visualizzare |
dataKey | string | 'id' | Campo che identifica univocamente ogni riga |
loading | boolean | false | Mostra indicatore di caricamento |
loadingIcon | string | undefined | Icona di caricamento custom |
lazy | boolean | false | Abilita lazy loading (paginazione/sort/filter server-side) |
stripedRows | boolean | false | Righe alternate con sfondo diverso |
showGridlines | boolean | false | Mostra linee di separazione celle |
size | 'small' | 'medium' | 'large' | 'medium' | Dimensione del componente |
showHeader | boolean | true | Mostra l'intestazione della tabella |
rowHover | boolean | true | Evidenzia riga al passaggio del mouse |
tableClass | string | — | Classe CSS aggiuntiva per la tabella |
tableStyle | string | Record<string, string | number> | — | Stile inline per la tabella |
scrollable | boolean | false | Abilita scroll orizzontale/verticale |
scrollHeight | string | '400px' | Altezza area di scroll |
virtualScrollerOptions | Record<string, unknown> | — | Opzioni del virtual scroller |
sortField | string | — | Campo di ordinamento iniziale |
sortOrder | 1 | -1 | 0 | null | null | Direzione ordinamento (1=asc, -1=desc) |
multiSortMeta | SortMeta[] | — | Metadati per ordinamento multi-colonna |
sortMode | 'single' | 'multiple' | 'single' | Modalità ordinamento |
removableSort | boolean | false | Permette di rimuovere l'ordinamento con un terzo click |
paginator | boolean | false | Abilita la paginazione |
rows | number | 10 | Numero di righe per pagina |
first | number | 0 | Indice della prima riga visualizzata |
totalRecords | number | — | Numero totale di record (necessario in lazy mode) |
rowsPerPageOptions | number[] | [10, 25, 50] | Opzioni per il dropdown righe per pagina |
pageLinkSize | number | 5 | Numero di link pagina da mostrare |
paginatorPosition | 'top' | 'bottom' | 'both' | 'bottom' | Posizione del paginatore |
alwaysShowPaginator | boolean | true | Mostra paginatore anche con una sola pagina |
currentPageReportTemplate | string | 'Showing {first} to {last} of {totalRecords} entries' | Template report pagina corrente |
paginatorTemplate | string | PaginatorTemplate | 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown' | Elementi del paginatore separati da spazio. Accetta un oggetto responsive: le chiavi '<N>px' valgono fino a quella larghezza (max-width), default oltre. Vedi Paginatore responsive |
filters | FilterMeta | — | Filtri attivi (v-model:filters) |
filterDisplay | 'menu' | 'row' | 'menu' | Modalità visualizzazione filtri |
globalFilterFields | string[] | — | Campi inclusi nel filtro globale |
selection | T | T[] | — | Righe selezionate (v-model:selection) |
selectionMode | 'single' | 'multiple' | 'checkbox' | undefined | Modalità selezione righe. Si può cambiare in qualsiasi momento (dalla 1.24.0; prima era letta solo al montaggio). Senza, vale quella di una <Column selection-mode> (vedi Selezione righe) |
metaKeySelection | boolean | true | Richiede Ctrl/Meta per selezione multipla. Reattiva come selectionMode |
compareSelectionBy | 'equals' | 'deepEquals' | — | Metodo di confronto per la selezione |
selectAll | boolean | — | Stato checkbox header (v-model:selectAll) |
selectionRowAriaLabel | (row: T, index: number) => string | — | Nome accessibile della casella di selezione di ogni riga (es. "Seleziona lead Rossi"). Ha priorità su selectionRowAriaLabelKey |
selectionRowAriaLabelKey | string | — | Campo della riga interpolato nell'etichetta i18n table.selectRow ("Seleziona riga {label}"). Senza nessuna delle due props l'etichetta usa il numero di riga |
expandedRows | T[] | — | Righe espanse (v-model:expandedRows) |
expandedRowIcon | string | — | Icona riga espansa |
collapsedRowIcon | string | — | Icona riga collassata |
editMode | 'cell' | 'row' | — | Modalità editing inline |
editingRows | T[] | — | Righe in fase di modifica (v-model:editingRows) |
rowGroupMode | 'subheader' | 'rowspan' | — | Modalità raggruppamento righe |
groupRowsBy | string | string[] | — | Campo per raggruppamento |
expandableRowGroups | boolean | — | Gruppi espandibili |
expandedRowGroups | unknown[] | — | Chiavi gruppi espansi (v-model:expandedRowGroups) |
resizableColumns | boolean | false | Abilita ridimensionamento colonne |
columnResizeMode | 'fit' | 'expand' | 'fit' | Modalità ridimensionamento |
reorderableColumns | boolean | false | Abilita riordinamento colonne tramite drag |
draggableRows | boolean | false | Righe trascinabili su un nodo di TreeTable o Tree con droppable; una riga selezionata trascina tutta la selezione (dalla 1.24.0). Vedi Righe trascinate su un albero |
contextMenu | boolean | — | Abilita menu contestuale al right-click |
contextMenuSelection | T | — | Riga selezionata via context menu (v-model:contextMenuSelection) |
frozenValue | T[] | — | Righe fisse in cima alla tabella |
frozenColumns | number | — | Numero di colonne frozen a sinistra |
stateStorage | 'session' | 'local' | — | Storage per persistenza stato |
stateKey | string | — | Chiave univoca per lo stato salvato |
responsiveLayout | 'scroll' | 'stack' | 'scroll' | Comportamento responsive |
breakpoint | string | '768px' | Breakpoint per layout stack |
csvSeparator | string | ';' | Separatore dei campi di exportCSV(). Default ; per Excel in italiano (dalla 1.22.0; prima la prop non aveva effetto) |
exportFilename | string | 'download' | Nome del file di exportCSV(), senza diacritici e con estensione .csv |
emptyMessage | string | — | Testo mostrato quando non ci sono dati |
rowClass | string | ((data: T) => string) | — | Classe CSS dinamica per riga |
rowStyle | Record<string, string | number> | ((data: T) => Record<string, string | number>) | — | Stile inline dinamico per riga |
Props — Column
| Prop | Tipo | Default | Descrizione |
|---|---|---|---|
field | string | — | Campo dati della colonna |
header | string | — | Testo intestazione |
footer | string | — | Testo footer |
columnKey | string | — | Chiave univoca della colonna. Raccomandata sulle colonne senza field (azioni, selezione): senza, la chiave è la posizione. Vedi Colonne senza field |
dataType | 'string' | 'number' | 'date' | 'boolean' | 'custom' | — | Tipo dato (determina allineamento automatico) |
sortable | boolean | false | Abilita ordinamento su questa colonna. Una colonna senza field né sortField non è ordinabile, anche con sortable (dalla 1.24.0) |
sortField | string | — | Campo usato per l'ordinamento, anche annidato (cliente.ragione); default field. Dalla 1.24.0 l'ordinamento lo usa davvero (prima ordinava su field) |
filterField | string | — | Campo usato per il filtro (default: field) |
filterMatchMode | string | — | Modalità di match per il filtro (attiva la colonna filtrabile) |
hidden | boolean | false | Nasconde la colonna |
hideAt | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | — | Nasconde la colonna sotto il breakpoint indicato ('2xl' dalla 1.24.0). Si applica a intestazione, celle body, riga filtri e cella footer |
responsivePriority | 1 | 2 | 3 | 4 | 5 | — | Alternativa a hideAt: 1 = sempre visibile, 2 = da sm, … 5 = solo da xl. hideAt ha la precedenza |
width | string | — | Larghezza colonna (es. '200px', '20%') |
minWidth | string | — | Larghezza minima |
maxWidth | string | — | Larghezza massima |
frozen | boolean | false | Colonna fissa durante lo scorrimento orizzontale; si può scrivere senza valore (<Column frozen />, dalla 1.24.0). Vedi Colonne fisse |
alignFrozen | 'left' | 'right' | 'left' | Lato della colonna frozen |
expander | boolean | false | Nel DataTable la freccia di espansione la aggiunge lo slot #expansion: una Column expander senza field né slot body non crea più una colonna vuota (dalla 1.24.0); con un contenuto proprio resta una colonna normale |
rowReorder | boolean | false | La colonna rende in ogni riga una maniglia di riordino, trascinabile o usabile da tastiera (dalla 1.22.0; prima la prop non aveva effetto). Vedi Riordino delle righe |
rowReorderIcon | string | — | Icona della maniglia (default icons.list.dragHandle) |
reorderableColumn | boolean | — | Permette di riordinare questa colonna |
rowEditor | boolean | false | La colonna mostra i controlli di editing riga |
selectionMode | 'single' | 'multiple' | 'checkbox' | — | Dichiara la colonna delle caselle di selezione: diventa quella che la tabella aggiunge da sé, non una colonna vuota in più, e fa da modalità della tabella se questa non ne ha una (multiple → checkbox, single → single) (dalla 1.24.0) |
exportable | boolean | true | Include la colonna in exportCSV() (servono anche field e colonna visibile) |
exportHeader | string | — | Intestazione della colonna nel CSV, al posto di header |
exportFooter | string | — | Valore della colonna nella riga di piede del CSV |
alignHeader | 'left' | 'center' | 'right' | 'left' | Allineamento intestazione |
alignBody | 'left' | 'center' | 'right' | — | Allineamento celle body (default: automatico da dataType) |
style | string | Record<string, string | number> | — | Stile cella |
class | string | Record<string, unknown> | — | Classe CSS cella |
headerStyle | string | Record<string, string | number> | — | Stile intestazione |
headerClass | string | Record<string, unknown> | — | Classe intestazione |
bodyStyle | string | Record<string, string | number> | — | Stile body |
bodyClass | string | Record<string, unknown> | — | Classe body. Con whitespace-normal la cella va a capo (dalla 1.24.0, vedi Colonne fisse) |
footerStyle | string | Record<string, string | number> | — | Stile cella footer |
footerClass | string | Record<string, unknown> | — | Classe cella footer |
aggregate | 'sum' | 'count' | 'avg' | 'min' | 'max' | ((rows: T[]) => unknown) | — | Aggregazione built-in da renderizzare nel footer della colonna. Calcolata su paginatedData (record visibili dopo filtri/paginazione). Lo slot #footer ha priorità su aggregate |
aggregateFormat | (value: unknown) => string | — | Funzione di formattazione del valore aggregato (es. valuta) |
colspan | number | — | Colspan per raggruppamento celle |
rowspan | number | — | Rowspan per raggruppamento celle |
excludeGlobalFilter | boolean | false | Esclude la colonna dal filtro globale |
showFilterMenu | boolean | true | Mostra menu filtro |
showFilterOperator | boolean | true | Mostra selector operatore filtro |
showClearButton | boolean | false | Mostra pulsante reset filtro |
showApplyButton | boolean | true | Mostra pulsante applica filtro |
showFilterMatchModes | boolean | true | Mostra selector match modes nel menu filtro |
filterMatchModeOptions | FilterMatchModeOption[] | — | Opzioni custom per match modes |
showAddButton | boolean | true | Mostra pulsante per aggiungere un constraint filtro |
maxConstraints | number | 2 | Numero massimo di filtri per colonna |
filterHeaderStyle | string | Record<string, string | number> | — | Stile cella header filtro |
filterHeaderClass | string | Record<string, unknown> | — | Classe cella header filtro |
filterMenuStyle | string | Record<string, string | number> | — | Stile menu filtro |
filterMenuClass | string | Record<string, unknown> | — | Classe menu filtro |
Le props booleane di Column si possono scrivere senza valore, come attributi HTML:
<Column frozen truncate /> vale :frozen="true" :truncate="true" (dalla 1.24.0; prima solo
sortable, hidden ed expander erano riconosciute così, e frozen senza valore non fissava
la colonna). Un valore assente resta il default: exportable resta true.
Emits
| Evento | Payload | Descrizione |
|---|---|---|
update:first | number | Cambio indice prima riga (paginazione) |
update:rows | number | Cambio righe per pagina |
update:sortField | string | Cambio campo di ordinamento |
update:sortOrder | SortOrder | Cambio direzione ordinamento |
update:multiSortMeta | SortMeta[] | Cambio metadati multi-sort |
update:selection | T | T[] | Cambio selezione righe |
update:filters | FilterMeta | Cambio filtri attivi |
update:expandedRows | T[] | Cambio righe espanse |
update:selectAll | boolean | Cambio stato "seleziona tutto" |
update:expandedRowGroups | unknown[] | Cambio gruppi espansi |
update:editingRows | T[] | Cambio righe in editing |
update:contextMenuSelection | T | Cambio selezione context menu |
page | PageEvent | Cambio pagina |
sort | SortEvent | Cambio ordinamento |
filter | FilterEvent | Applicazione filtro |
rowClick | RowClickEvent<T> | Click su una riga |
rowDblclick | RowClickEvent<T> | Doppio click su una riga |
rowSelect | RowSelectEvent<T> | Riga selezionata |
rowUnselect | RowSelectEvent<T> | Riga deselezionata |
rowSelectAll | { originalEvent: Event; data: T[] } | Selezionate tutte le righe |
rowUnselectAll | { originalEvent: Event } | Deselezionate tutte le righe |
rowExpand | { data: T } | Riga espansa |
rowCollapse | { data: T } | Riga collassata |
rowContextmenu | { originalEvent: MouseEvent; data: T; index: number } | Right-click su riga |
columnReorder | { dragIndex: number; dropIndex: number; columns: unknown[] } | Colonne riordinate |
rowReorder | { originalEvent: Event; dragIndex: number; dropIndex: number; value: T[] } | Riga spostata con la colonna rowReorder: indici di value e copia riordinata da assegnare alla tabella (dalla 1.22.0) |
columnResize | { element: HTMLElement; delta: number } | Colonna ridimensionata |
cellEditInit | { data: T; field: string; index: number } | Inizio editing cella |
cellEditComplete | { data: T; field: string; newValue: unknown; index: number } | Editing cella completato |
cellEditCancel | { data: T; field: string; index: number } | Editing cella annullato |
rowEditInit | { data: T; index: number } | Inizio editing riga |
rowEditSave | { data: T; newData: T; index: number } | Editing riga salvato |
rowEditCancel | { data: T; index: number } | Editing riga annullato |
rowgroupExpand | { originalEvent: Event; data: unknown } | Gruppo espanso |
rowgroupCollapse | { originalEvent: Event; data: unknown } | Gruppo collassato |
stateSave | { state: TableState } | Stato salvato |
stateRestore | { state: TableState } | Stato ripristinato |
valueChange | T[] | Dati processati cambiati |
Slot — DataTable
| Slot | Scope | Descrizione |
|---|---|---|
default | — | Posizione per i componenti Column |
header | — | Contenuto sopra la tabella |
footer | — | Riga footer full-width sotto la tabella (renderizzata come <td colspan> unico). Convive con i footer per-Column |
table-footer | — | Slot passato a BaseTable per contenuto sotto il body (sopra il paginator bottom) |
empty | — | Template per stato vuoto (nessun dato) |
loading | — | Template per stato di caricamento |
expansion | { data: T; index: number } | Contenuto riga espansa |
groupheader | { data: T[]; value: unknown; expanded: boolean } | Header gruppo righe |
groupfooter | { data: T[]; value: unknown } | Footer gruppo righe |
rowgrouptogglericon | { expanded: boolean } | Icona toggle del gruppo righe espandibile |
paginatorstart | — | Contenuto a sinistra del paginatore |
paginatorend | — | Contenuto a destra del paginatore |
bulkactions | { selection: T[]; count: number; clearSelection: () => void } | Azioni sulla selezione, nella barra che compare con almeno una riga selezionata (accanto al conteggio e a «Deseleziona tutto») |
paginatorcontainer | PaginatorContainerProps | Container paginatore completamente custom |
paginatorfirstpagelinkicon | { class: string } | Icona "prima pagina" |
paginatorprevpagelinkicon | { class: string } | Icona "pagina precedente" |
paginatornextpagelinkicon | { class: string } | Icona "pagina successiva" |
paginatorlastpagelinkicon | { class: string } | Icona "ultima pagina" |
paginatorrowsperpagedropdownicon | { class: string } | Icona dropdown righe per pagina |
paginatorjumptopagedropdownicon | { class: string } | Icona dropdown jump-to-page |
loadingicon | — | Icona loading custom |
reorderindicatorupicon | — | Indicatore reorder colonna (su) |
reorderindicatordownicon | — | Indicatore reorder colonna (giù) |
rowreorderindicatorupicon | — | Indicatore reorder riga (su) |
rowreorderindicatordownicon | — | Indicatore reorder riga (giù) |
body-{field} | { data: T; field: string; index: number; column: ColumnProps } | Template body per campo specifico (alternativa agli slot di Column) |
Slot — Column
| Slot | Scope | Descrizione |
|---|---|---|
body | { data: T; field: string; index: number; column: ColumnProps } | Template cella body. Il contenuto non viene ricreato quando la tabella si ridisegna: un campo nella cella mantiene focus e valore mentre si digita (dalla 1.24.0; prima ogni ridisegno lo rimontava) |
header | { column: ColumnProps } | Template intestazione: sostituisce il testo di header nella cella, anche nelle colonne ordinabili. La prop header resta utile come testo di title, data-label (layout stack) e nomi accessibili dei filtri |
footer | { column: ColumnProps; value: unknown } | Template footer per-colonna. value è il risultato dell'aggregazione (o undefined se aggregate non è configurato). Lo slot ha priorità su aggregate e prop footer |
filter | { field: string; filterModel: unknown; filterCallback: () => void } | Template filtro custom |
editor | { data: T; field: string; index: number; editorCallback: (value: unknown) => void } | Template editor inline |
loading | — | Template loading custom per virtual scroll |
sorticon | { sorted: boolean; sortOrder: number | null } | Icona sort custom |
filtericon | — | Icona menu filtro |
filterclearicon | — | Icona clear filtro |
filterapplyicon | — | Icona apply filtro |
filteraddicon | — | Icona add filtro |
filterremoveicon | — | Icona remove filtro |
rowreordericon | — | Icona handle reorder riga |
rowtoggleicon | { expanded: boolean } | Icona toggle expander riga |
Esempi
Ordinamento
Con sort-field la colonna ordina su un campo diverso da quello mostrato, anche annidato:
<Column field="cliente" sort-field="cliente.ragione" header="Cliente" sortable>
<template #body="{ data }">{{ data.cliente.ragione }}</template>
</Column>
Filtri per riga
Selezione righe
selection-mode sulla tabella si può cambiare quando serve, per esempio per attivare la
selezione solo in una modalità «modifica». In alternativa basta <Column selection-mode="multiple" />
senza selection-mode sulla tabella: la colonna diventa quella delle caselle (equivale a
selection-mode="checkbox"). Con almeno una riga selezionata compare la barra con il
conteggio, «Deseleziona tutto» e lo slot bulkactions per le azioni sulla selezione.
Nome contestuale della casella di selezione
Di default ogni casella si chiama "Seleziona riga N", che a uno screen reader non dice quale record si sta selezionando. selectionRowAriaLabel costruisce il nome dalla riga; in alternativa selectionRowAriaLabelKey indica il campo da interpolare nell'etichetta i18n table.selectRow.
<DataTable
v-model:selection="selezionati"
:value="lead"
data-key="idlead"
selection-mode="multiple"
:selection-row-aria-label="(riga) => `Seleziona lead ${riga.cognome}`"
>
<Column field="cognome" header="Cognome" />
</DataTable>
<!-- casella della prima riga: aria-label="Seleziona lead Rossi" -->
<!-- Oppure, con l'etichetta i18n standard: "Seleziona riga Rossi" -->
<DataTable :value="lead" selection-mode="multiple" selection-row-aria-label-key="cognome">
…
</DataTable>
Espansione riga
La freccia di espansione la aggiunge lo slot #expansion: non serve una <Column expander />,
che senza field né slot body non genera colonne (prima aggiungeva una colonna vuota).
Footer per-Column e aggregazioni built-in
Ogni Column può definire uno slot #footer per-colonna, una prop footer: string testuale, oppure una prop aggregate che produce un'aggregazione built-in (sum, count, avg, min, max) o una funzione custom (rows) => unknown. Le aggregazioni vengono calcolate sui dati della pagina corrente (paginatedData, già filtrati e paginati). Lo slot #footer ha priorità su aggregate, che a sua volta vince sulla prop footer. Se nessuna colonna definisce contenuto footer, il <tfoot> non viene renderizzato (backward-compatible).
Regole di priorità per la cella footer (alta → bassa):
- Slot
#footer="{ column, value }"definito sullaColumn - Prop
aggregate(con eventualeaggregateFormat) - Prop
footer: string(testo statico) - Cella vuota
Funzioni di aggregazione built-in:
Valore aggregate | Comportamento |
|---|---|
'sum' | Somma dei valori numerici del field (ignora null/undefined/NaN) |
'count' | Numero di righe con valore non null/undefined nel field |
'avg' | Media dei valori numerici del field (0 se vuoto) |
'min' | Minimo dei valori numerici del field (undefined se vuoto) |
'max' | Massimo dei valori numerici del field (undefined se vuoto) |
(rows: T[]) => unknown | Funzione custom che riceve le righe della pagina corrente |
Lo slot
footerdelDataTable(riga full-widthcolspan) può coesistere con i footer per-Column: viene renderizzata come riga separata dopo quella per-colonna.
La cella footer eredita hideAt / responsivePriority della sua colonna: una riga "Totale" non resta visibile nelle colonne nascoste sotto il breakpoint, quindi non serve replicare le classi responsive in footerClass.
Colonne senza field
Una Column è riconosciuta anche senza field né header (tipicamente la colonna delle azioni) e ogni colonna ha una chiave univoca, calcolata così:
columnKey, se presente;- altrimenti
field; - altrimenti la posizione della colonna.
Se due colonne hanno la stessa chiave, la seconda riceve un suffisso posizionale: allineamento, hideAt e stili restano sempre della colonna giusta. Per le colonne senza field è comunque raccomandato un columnKey esplicito, stabile anche se l'ordine delle colonne cambia.
<DataTable :value="lead" caption="Lead">
<Column field="cognome" header="Cognome" />
<Column field="valore" header="Valore" data-type="number" hide-at="md" />
<Column column-key="azioni" align-body="right">
<template #header><span class="sr-only">Azioni</span></template>
<template #body="{ data }">
<Button icon="pi pi-pencil" text aria-label="Modifica" @click="modifica(data)" />
</template>
</Column>
</DataTable>
Lo slot #header della Column sostituisce il testo dell'intestazione, anche nelle colonne ordinabili (resta dentro il pulsante di ordinamento).
Colonne fisse
frozen fissa la colonna a sinistra durante lo scorrimento orizzontale (scrollable), con
align-frozen="right" a destra. La cella fissa ha sempre uno sfondo opaco, così le colonne che
le scorrono sotto non traspaiono: in intestazione e piede quello del <thead>/<tfoot>
(--color-surface-secondary), nel corpo quello della riga, anche selezionata o in hover
(dalla 1.24.0). La riga selezionata usa i token opachi --color-surface-selected e
--color-surface-selected-hover (vedi Proprietà CSS); con
striped-rows l'hover si vede anche sulle righe pari.
Se un modulo forzava lo sfondo dell'intestazione fissa con header-style (il workaround delle
versioni precedenti), va tolto: nel tema scuro la renderebbe più chiara del resto.
A capo. Le celle non vanno a capo, ma dalla 1.24.0 la regola sta in @layer components:
una utility del chiamante la sostituisce, quindi body-class="whitespace-normal" (o
header-class) manda a capo il testo. Prima la regola era fuori dai layer e vinceva sempre.
Righe trascinate su un albero
Con draggable-rows (dalla 1.24.0) le righe si trascinano su un nodo di una
TreeTable o di un Tree con droppable,
che emette nodeDrop con { node, data, originalEvent }: data sono le righe trascinate, e una
riga che fa parte della selezione trascina tutta la selezione. È il gesto per spostare documenti
in una cartella; il riordino nella stessa tabella resta la colonna rowReorder, la cui maniglia
mantiene il proprio trascinamento.
<DataTable v-model:selection="scelti" :value="documenti" data-key="id" selection-mode="multiple" draggable-rows>
<Column field="nome" header="Documento" />
</DataTable>
<TreeTable :value="cartelle" droppable caption="Cartelle" @node-drop="({ node, data }) => sposta(data, node.key)">
<Column field="nome" header="Cartella" expander />
</TreeTable>
Il trascinamento richiede un puntatore: da tastiera serve un'alternativa equivalente, per esempio un'azione «Sposta in…» sulle righe selezionate.
Paginatore responsive
paginatorTemplate sceglie quali elementi del paginatore mostrare (vedi le chiavi in Paginator). Con un oggetto il template cambia con la larghezza del viewport: ogni chiave '<N>px' vale fino a quella larghezza (max-width), vince la più stretta che corrisponde, default si applica oltre. Esempio: a 390px il paginatore completo fa scorrere la pagina, quindi su schermi stretti restano solo le frecce e il report.
<script setup lang="ts">
import type { PaginatorTemplate } from '@pzeta/vue-components'
const template: PaginatorTemplate = {
'640px': 'PrevPageLink CurrentPageReport NextPageLink',
default: 'FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown',
}
</script>
<template>
<DataTable :value="lead" paginator :rows="10" :paginator-template="template">
<Column field="cognome" header="Cognome" />
</DataTable>
</template>
Lazy Loading (server-side)
<script setup lang="ts">
import { ref } from 'vue'
import type { DataTablePageEvent, DataTableSortEvent } from '@pzeta/vue-components'
const products = ref<Product[]>([])
const totalRecords = ref(0)
const loading = ref(false)
async function loadData(event: DataTablePageEvent) {
loading.value = true
const { data, total } = await fetchProducts({
first: event.first,
rows: event.rows,
})
products.value = data
totalRecords.value = total
loading.value = false
}
</script>
<template>
<DataTable
:value="products"
:total-records="totalRecords"
:loading="loading"
:lazy="true"
:paginator="true"
:rows="10"
@page="loadData"
@sort="loadData"
>
<Column field="name" header="Nome" :sortable="true" />
<Column field="price" header="Prezzo" :sortable="true" data-type="number" />
</DataTable>
</template>
Editing inline (cell mode)
Riordino delle righe
Una <Column row-reorder /> rende in ogni riga una maniglia (dalla 1.22.0): si trascina sulla
riga di arrivo, oppure col focus sulla maniglia Spazio/Invio afferra, frecce,
Home e Fine scelgono la posizione, Spazio/Invio rilascia ed Esc annulla
(senza chiudere un Dialog contenitore). Il DataTable non cambia value: emette rowReorder
con dragIndex e dropIndex (indici di value) e value già riordinato. Dopo un rilascio da
tastiera il focus resta sulla maniglia della riga spostata.
Con ordinamento o filtri attivi la riga si sposta al posto della riga di arrivo nell'ordine di
value, ma la vista resta ordinata: il riordino ha senso senza ordinamento.
Esportazione CSV
exportCSV(options?) (dalla 1.22.0) scarica le colonne visibili con un field e senza
:exportable="false", con le righe filtrate e ordinate di tutte le pagine;
exportCSV({ selectionOnly: true }) esporta solo le selezionate. Esporta il valore del campo,
non il testo formattato della cella, così il foglio di calcolo legge numeri e date come tali.
export-header sostituisce l'intestazione, export-footer aggiunge una riga di piede. Il file
usa le regole dell'utility exportCsv:
separatore csvSeparator (default ;), virgola decimale, BOM UTF-8, quotatura RFC 4180,
neutralizzazione delle formule.
Allineamento automatico per dataType
L'allineamento delle celle body viene determinato automaticamente dal dataType se alignBody non è specificato esplicitamente:
| dataType | Allineamento body |
|---|---|
string | sinistra |
number | destra |
date | centro |
boolean | centro |
L'header è sempre allineato a sinistra per default. Usa alignHeader e alignBody per override esplicito.
Metodi esposti (defineExpose)
Accessibili via templateRef.value.* quando si ottiene un ref al DataTable.
| Metodo / Proprietà | Descrizione |
|---|---|
onFilter(field, value, matchMode?) | Applica programmaticamente un filtro su una colonna |
getFilterValue(field) | Restituisce il valore del filtro corrente per il campo |
hasActiveFilter(field) | Verifica se una colonna ha un filtro attivo |
clearFilter(field) | Rimuove il filtro di una colonna |
clearAllFilters() | Rimuove tutti i filtri attivi |
processedData | Computed con i dati dopo filtro e ordinamento (tutta la tabella) |
paginatedData | Computed con i dati della pagina corrente |
isCellEditing(rowKey, field) | True se la cella è in editing |
isRowEditing(row) | True se la riga è in editing |
onCellEditInit(data, field, index) | Inizia l'editing di una cella |
onCellEditComplete(data, field, newValue, index) | Completa l'editing di una cella |
onCellEditCancel(data, field, index) | Annulla l'editing di una cella |
onRowEditInit(data, index) | Inizia l'editing di una riga |
onRowEditSave(data, newData, index) | Salva l'editing di una riga |
onRowEditCancel(data, index) | Annulla l'editing di una riga |
getEditingRows() | Restituisce le righe attualmente in editing |
saveState() | Salva lo stato corrente nello storage configurato |
restoreState() | Ripristina lo stato dallo storage |
clearState() | Cancella lo stato salvato |
createState() | Crea uno snapshot dello stato senza salvarlo |
exportCSV(options?) | Scarica il CSV delle colonne visibili esportabili; options.selectionOnly per le sole righe selezionate (dalla 1.22.0) |
Accessibilità
La tabella usa markup semantico <table>, <thead>, <th>, <td>. Le colonne ordinabili ricevono l'attributo aria-sort (solo quelle con un campo su cui ordinare). Gli attributi aria-* passati al DataTable (aria-label, aria-labelledby, aria-describedby…) finiscono sulla <table>, mentre classi, data-* e il resto restano sul contenitore (dalla 1.24.0; prima finivano tutti sul contenitore e non nominavano la tabella). Il paginatore interno usa <nav> con aria-label localizzato tramite il sistema i18n. Le caselle di selezione di riga prendono un nome contestuale con selectionRowAriaLabel / selectionRowAriaLabelKey (vedi Selezione righe).
TypeScript
import type {
DataTableProps,
DataTableEmits,
DataTableFilterMeta,
DataTableSortMeta,
DataTablePageEvent,
DataTableSortEvent,
DataTableFilterEvent,
DataTableRowClickEvent,
DataTableRowSelectEvent,
DataTableState,
ColumnProps,
ColumnSlots,
} from '@pzeta/vue-components'
Chart
Wrapper Vue 3 per Chart.js che supporta grafici bar, line, pie, doughnut, radar, polarArea, bubble e scatter con aggiornamento reattivo.
DataView
Componente per visualizzare collezioni di dati in layout lista o griglia, con paginazione e ordinamento integrati. I template list e grid sono completamente personalizzabili tramite slot.