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 |
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 |
metaKeySelection | boolean | true | Richiede Ctrl/Meta per selezione multipla |
compareSelectionBy | 'equals' | 'deepEquals' | — | Metodo di confronto per la selezione |
selectAll | boolean | — | Stato checkbox header (v-model:selectAll) |
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 |
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 CSV per export |
exportFilename | string | 'download' | Nome file per export 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 se field non è definito |
dataType | 'string' | 'number' | 'date' | 'boolean' | 'custom' | — | Tipo dato (determina allineamento automatico) |
sortable | boolean | false | Abilita ordinamento su questa colonna |
sortField | string | — | Campo usato per l'ordinamento (default: 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 |
width | string | — | Larghezza colonna (es. '200px', '20%') |
minWidth | string | — | Larghezza minima |
maxWidth | string | — | Larghezza massima |
frozen | boolean | false | Colonna fissa (frozen) |
alignFrozen | 'left' | 'right' | 'left' | Lato della colonna frozen |
expander | boolean | false | La colonna mostra il pulsante di espansione riga |
rowReorder | boolean | false | La colonna abilita drag-and-drop riordinamento righe |
rowReorderIcon | string | — | Icona per il drag handle del riordinamento |
reorderableColumn | boolean | — | Permette di riordinare questa colonna |
rowEditor | boolean | false | La colonna mostra i controlli di editing riga |
selectionMode | 'single' | 'multiple' | 'checkbox' | — | Rende questa colonna la colonna di selezione |
exportable | boolean | true | Include la colonna nell'export CSV |
exportHeader | string | — | Header usato nell'export CSV |
exportFooter | string | — | Footer usato nell'export 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 |
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 |
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 | { dragIndex: number; dropIndex: number; value: T[] } | Righe riordinate via drag |
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 |
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 |
header | { column: ColumnProps } | Template intestazione |
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
Filtri per riga
Selezione righe
Espansione riga
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.
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)
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 |
Accessibilità
La tabella usa markup semantico <table>, <thead>, <th>, <td>. Le colonne ordinabili ricevono l'attributo aria-sort. Il paginatore interno usa <nav> con aria-label localizzato tramite il sistema i18n.
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.