Data

DataTable

Tabella dati avanzata con supporto per ordinamento, filtri, paginazione, selezione righe, espansione e raggruppamento. Il sub-componente Column definisce le colonne in modo dichiarativo.

Import

import { DataTable, Column } from '@pzeta/vue-components'
import type {
  DataTableProps,
  DataTableEmits,
  DataTableFilterMeta,
  DataTableSortMeta,
  ColumnProps,
} from '@pzeta/vue-components'

Esempio Base

Props — DataTable

PropTipoDefaultDescrizione
valueT[][]Array di dati da visualizzare
dataKeystring'id'Campo che identifica univocamente ogni riga
loadingbooleanfalseMostra indicatore di caricamento
loadingIconstringundefinedIcona di caricamento custom
lazybooleanfalseAbilita lazy loading (paginazione/sort/filter server-side)
stripedRowsbooleanfalseRighe alternate con sfondo diverso
showGridlinesbooleanfalseMostra linee di separazione celle
size'small' | 'medium' | 'large''medium'Dimensione del componente
showHeaderbooleantrueMostra l'intestazione della tabella
rowHoverbooleantrueEvidenzia riga al passaggio del mouse
tableClassstring—Classe CSS aggiuntiva per la tabella
tableStylestring | Record<string, string | number>—Stile inline per la tabella
scrollablebooleanfalseAbilita scroll orizzontale/verticale
scrollHeightstring'400px'Altezza area di scroll
virtualScrollerOptionsRecord<string, unknown>—Opzioni del virtual scroller
sortFieldstring—Campo di ordinamento iniziale
sortOrder1 | -1 | 0 | nullnullDirezione ordinamento (1=asc, -1=desc)
multiSortMetaSortMeta[]—Metadati per ordinamento multi-colonna
sortMode'single' | 'multiple''single'Modalità ordinamento
removableSortbooleanfalsePermette di rimuovere l'ordinamento con un terzo click
paginatorbooleanfalseAbilita la paginazione
rowsnumber10Numero di righe per pagina
firstnumber0Indice della prima riga visualizzata
totalRecordsnumber—Numero totale di record (necessario in lazy mode)
rowsPerPageOptionsnumber[][10, 25, 50]Opzioni per il dropdown righe per pagina
pageLinkSizenumber5Numero di link pagina da mostrare
paginatorPosition'top' | 'bottom' | 'both''bottom'Posizione del paginatore
alwaysShowPaginatorbooleantrueMostra paginatore anche con una sola pagina
currentPageReportTemplatestring'Showing {first} to {last} of {totalRecords} entries'Template report pagina corrente
paginatorTemplatestring | 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
filtersFilterMeta—Filtri attivi (v-model:filters)
filterDisplay'menu' | 'row''menu'Modalità visualizzazione filtri
globalFilterFieldsstring[]—Campi inclusi nel filtro globale
selectionT | T[]—Righe selezionate (v-model:selection)
selectionMode'single' | 'multiple' | 'checkbox'undefinedModalità 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)
metaKeySelectionbooleantrueRichiede Ctrl/Meta per selezione multipla. Reattiva come selectionMode
compareSelectionBy'equals' | 'deepEquals'—Metodo di confronto per la selezione
selectAllboolean—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
selectionRowAriaLabelKeystring—Campo della riga interpolato nell'etichetta i18n table.selectRow ("Seleziona riga {label}"). Senza nessuna delle due props l'etichetta usa il numero di riga
expandedRowsT[]—Righe espanse (v-model:expandedRows)
expandedRowIconstring—Icona riga espansa
collapsedRowIconstring—Icona riga collassata
editMode'cell' | 'row'—Modalità editing inline
editingRowsT[]—Righe in fase di modifica (v-model:editingRows)
rowGroupMode'subheader' | 'rowspan'—Modalità raggruppamento righe
groupRowsBystring | string[]—Campo per raggruppamento
expandableRowGroupsboolean—Gruppi espandibili
expandedRowGroupsunknown[]—Chiavi gruppi espansi (v-model:expandedRowGroups)
resizableColumnsbooleanfalseAbilita ridimensionamento colonne
columnResizeMode'fit' | 'expand''fit'Modalità ridimensionamento
reorderableColumnsbooleanfalseAbilita riordinamento colonne tramite drag
draggableRowsbooleanfalseRighe 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
contextMenuboolean—Abilita menu contestuale al right-click
contextMenuSelectionT—Riga selezionata via context menu (v-model:contextMenuSelection)
frozenValueT[]—Righe fisse in cima alla tabella
frozenColumnsnumber—Numero di colonne frozen a sinistra
stateStorage'session' | 'local'—Storage per persistenza stato
stateKeystring—Chiave univoca per lo stato salvato
responsiveLayout'scroll' | 'stack''scroll'Comportamento responsive
breakpointstring'768px'Breakpoint per layout stack
csvSeparatorstring';'Separatore dei campi di exportCSV(). Default ; per Excel in italiano (dalla 1.22.0; prima la prop non aveva effetto)
exportFilenamestring'download'Nome del file di exportCSV(), senza diacritici e con estensione .csv
emptyMessagestring—Testo mostrato quando non ci sono dati
rowClassstring | ((data: T) => string)—Classe CSS dinamica per riga
rowStyleRecord<string, string | number> | ((data: T) => Record<string, string | number>)—Stile inline dinamico per riga

Props — Column

PropTipoDefaultDescrizione
fieldstring—Campo dati della colonna
headerstring—Testo intestazione
footerstring—Testo footer
columnKeystring—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)
sortablebooleanfalseAbilita ordinamento su questa colonna. Una colonna senza field né sortField non è ordinabile, anche con sortable (dalla 1.24.0)
sortFieldstring—Campo usato per l'ordinamento, anche annidato (cliente.ragione); default field. Dalla 1.24.0 l'ordinamento lo usa davvero (prima ordinava su field)
filterFieldstring—Campo usato per il filtro (default: field)
filterMatchModestring—Modalità di match per il filtro (attiva la colonna filtrabile)
hiddenbooleanfalseNasconde 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
responsivePriority1 | 2 | 3 | 4 | 5—Alternativa a hideAt: 1 = sempre visibile, 2 = da sm, … 5 = solo da xl. hideAt ha la precedenza
widthstring—Larghezza colonna (es. '200px', '20%')
minWidthstring—Larghezza minima
maxWidthstring—Larghezza massima
frozenbooleanfalseColonna 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
expanderbooleanfalseNel 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
rowReorderbooleanfalseLa 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
rowReorderIconstring—Icona della maniglia (default icons.list.dragHandle)
reorderableColumnboolean—Permette di riordinare questa colonna
rowEditorbooleanfalseLa 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)
exportablebooleantrueInclude la colonna in exportCSV() (servono anche field e colonna visibile)
exportHeaderstring—Intestazione della colonna nel CSV, al posto di header
exportFooterstring—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)
stylestring | Record<string, string | number>—Stile cella
classstring | Record<string, unknown>—Classe CSS cella
headerStylestring | Record<string, string | number>—Stile intestazione
headerClassstring | Record<string, unknown>—Classe intestazione
bodyStylestring | Record<string, string | number>—Stile body
bodyClassstring | Record<string, unknown>—Classe body. Con whitespace-normal la cella va a capo (dalla 1.24.0, vedi Colonne fisse)
footerStylestring | Record<string, string | number>—Stile cella footer
footerClassstring | 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)
colspannumber—Colspan per raggruppamento celle
rowspannumber—Rowspan per raggruppamento celle
excludeGlobalFilterbooleanfalseEsclude la colonna dal filtro globale
showFilterMenubooleantrueMostra menu filtro
showFilterOperatorbooleantrueMostra selector operatore filtro
showClearButtonbooleanfalseMostra pulsante reset filtro
showApplyButtonbooleantrueMostra pulsante applica filtro
showFilterMatchModesbooleantrueMostra selector match modes nel menu filtro
filterMatchModeOptionsFilterMatchModeOption[]—Opzioni custom per match modes
showAddButtonbooleantrueMostra pulsante per aggiungere un constraint filtro
maxConstraintsnumber2Numero massimo di filtri per colonna
filterHeaderStylestring | Record<string, string | number>—Stile cella header filtro
filterHeaderClassstring | Record<string, unknown>—Classe cella header filtro
filterMenuStylestring | Record<string, string | number>—Stile menu filtro
filterMenuClassstring | 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

EventoPayloadDescrizione
update:firstnumberCambio indice prima riga (paginazione)
update:rowsnumberCambio righe per pagina
update:sortFieldstringCambio campo di ordinamento
update:sortOrderSortOrderCambio direzione ordinamento
update:multiSortMetaSortMeta[]Cambio metadati multi-sort
update:selectionT | T[]Cambio selezione righe
update:filtersFilterMetaCambio filtri attivi
update:expandedRowsT[]Cambio righe espanse
update:selectAllbooleanCambio stato "seleziona tutto"
update:expandedRowGroupsunknown[]Cambio gruppi espansi
update:editingRowsT[]Cambio righe in editing
update:contextMenuSelectionTCambio selezione context menu
pagePageEventCambio pagina
sortSortEventCambio ordinamento
filterFilterEventApplicazione filtro
rowClickRowClickEvent<T>Click su una riga
rowDblclickRowClickEvent<T>Doppio click su una riga
rowSelectRowSelectEvent<T>Riga selezionata
rowUnselectRowSelectEvent<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
valueChangeT[]Dati processati cambiati

Slot — DataTable

SlotScopeDescrizione
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»)
paginatorcontainerPaginatorContainerPropsContainer 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

SlotScopeDescrizione
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).

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):

  1. Slot #footer="{ column, value }" definito sulla Column
  2. Prop aggregate (con eventuale aggregateFormat)
  3. Prop footer: string (testo statico)
  4. Cella vuota

Funzioni di aggregazione built-in:

Valore aggregateComportamento
'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[]) => unknownFunzione custom che riceve le righe della pagina corrente

Lo slot footer del DataTable (riga full-width colspan) 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ì:

  1. columnKey, se presente;
  2. altrimenti field;
  3. 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:

dataTypeAllineamento body
stringsinistra
numberdestra
datecentro
booleancentro

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
processedDataComputed con i dati dopo filtro e ordinamento (tutta la tabella)
paginatedDataComputed 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'