DataTable requires a collection to display along with Column components for the representation of the data.
Use the size property with small or large to adjust cell padding. Omit for the default size.
Enabling showGridlines displays borders between cells.
Alternating rows are displayed when stripedRows property is present.
One row at a time. Clicking a different row replaces the previous selection.
Multiple rows without a dedicated column. Pair with metaKeySelection so Ctrl/Cmd + Click toggles rows and Shift + Click selects a range; a plain click still replaces the selection.
Checkbox-based multiple selection with a header select-all checkbox. Specify selectionMode as multiple on a Column to display a checkbox inside that column along with a header checkbox to toggle the whole dataset.
Radio-based single selection. Specify selectionMode as single on a Column to display a radio button inside that column for selection.
Arrow Up/Down moves focus between rows, Space or Enter toggles the focused row, and Shift + Arrow extends a range. Paired with selectionMode multiple and metaKeySelection, the whole flow is keyboard-driven.
DataTable provides row-select and row-unselect events to listen selection events.
Clicking a column header cycles through ascending, descending, and unsorted. Add the sortable property to enable sorting on a column.
Hold Ctrl/Cmd and click multiple column headers to sort by several fields at once. Set sortMode to multiple to enable.
Apply an initial sort on mount using sortField and sortOrder. Headers stay interactive afterwards.
Apply an initial multi-column sort on mount by setting sortMode to multiple together with multiSortMeta. Each header keeps a badge with its sort order and stays interactive afterwards.
When removableSort is present, the third click removes the sorting from the column.
Pagination is enabled by setting paginator property to true and defining a rows property to specify the number of rows per page.
Paginator can also be controlled via model using a binding to the first property where changes trigger a pagination.
A fixed scrollHeight enables vertical scrolling with a sticky header.
When the combined column widths exceed the container, the table scrolls horizontally. Give each column a minWidth so the columns don't squeeze.
scrollHeight="flex" lets the viewport grow and shrink with its flex parent — handy inside resizable dialogs or split layouts.
Certain columns can be frozen by using the frozen property of the column. In addition, alignFrozen is available to define whether the column should be fixed on the left or right.
Multiple columns can be frozen on either side of the table. Enable the frozen property on each column to pin it during horizontal scroll and use alignFrozen to fix a column to the left (default) or the right edge.
Frozen rows are used to fix certain rows while scrolling, this data is defined with the frozenValue property.
Expand rows to show additional detail content. Use the row toggler callback to toggle expansion with expand/collapse icons.
Cell editing is enabled by setting editMode as cell, defining input elements with editor slot of a Column and implementing cell-edit-complete to update the state.
Cell editing composes with row selection. Clicks inside an editable cell start editing, while the checkbox column drives selection independently.
Row editing is configured with setting editMode as row and defining editingRows with the v-model directive to hold the reference of the editing rows. Similarly with cell edit mode, defining input elements with editor slot of a Column and implementing row-edit-save are necessary to update the state. A special rowEditor Column displays the editing controls, and a dataKey is required to uniquely identify each row.
Rows are grouped with the groupRowsBy property. When rowGroupMode is set as subheader, a header and footer can be displayed for each group. The content of a group header is provided with groupheader and footer with groupfooter slots.
When rowGroupMode is configured to be rowspan, the grouping column spans multiple rows.
When expandableRowGroups is present in subheader based row grouping, groups can be expanded and collapsed. State of the expansions are controlled using the expandedRows property and rowgroup-expand and rowgroup-collapse events.
Dragging a column takes width from the adjacent column so the total table width stays the same. Both demos enable showGridlines to make the effect visible.
Dragging grows or shrinks the whole table; adjacent columns keep their widths. Usually paired with scrollable so the table can exceed its viewport.
Resizable columns can be combined with scrollable tables to keep headers and the resize handles aligned while the body scrolls.
Drag and drop column headers to reorder columns.
Drag and drop rows to reorder data.
Show/hide columns dynamically.
Multi-level headers with rowspan and colspan.
Sort and filter work on any leaf header cell in a grouped layout. Add sortable with a field to the leaf header columns and a filter row below them with the filter templates.
Product | Sale Rate | Profits | ||
|---|---|---|---|---|
Last Year | This Year | Last Year | This Year | |
| Bamboo Watch | 51% | 40% | $54,406 | $43,342 |
| Black Watch | 83% | 9% | $423,132 | $312,122 |
| Blue Band | 38% | 5% | $12,321 | $8,500 |
| Blue T-Shirt | 49% | 22% | $745,232 | $650,323 |
| Bracelet | 17% | 79% | $643,242 | $500,332 |
Data filtering is enabled by defining the filters model referring to a DataTableFilterMeta instance and enabling the filterDisplay as row. Each column to filter also requires a filter template to customize the filtering with your own UI. This template receives a filterModel and filterCallback to build your own filter element.
The optional global filtering searches the data against a single value that is bound to the global key of the filters object. The fields to search against are defined with the globalFilterFields.
Name | Country | Status | Balance | Verified |
|---|---|---|---|---|
Any | ||||
| Amy Elsner | Germany | unqualified | $9,702 | — |
| Anna Fali | France | qualified | $12,500 | Verified |
| Asiya Javayant | India | new | $8,300 | — |
| Bernardo Dominic | USA | renewal | $24,100 | Verified |
| Elwin Sharvill | UK | qualified | $16,200 | Verified |
| Ioni Bowcher | Brazil | unqualified | $4,200 | — |
| Ivan Magalhaes | Brazil | new | $18,700 | Verified |
| Onyama Limba | Nigeria | qualified | $29,300 | — |
| Stephen Shaw | UK | negotiation | $15,800 | Verified |
| Xuxue Feng | China | renewal | $44,500 | Verified |
filterDisplay="menu" swaps the inline input for a trigger icon that opens a popover. Advanced fields expose a match mode per constraint with Apply and Clear actions, and the Name column stacks up to three rules joined by an AND/OR operator, while simpler fields provide a single editor.
Export table data to CSV with customizable fields and headers.
Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking corresponding callbacks everytime paging, sorting and filtering occurs. Sample below imitates lazy loading data from a remote datasource using an in-memory list and timeouts to mimic network connection.
Enabling the lazy property and assigning the logical number of rows to totalRecords by doing a projection query are the key elements of the implementation so that paginator displays the UI assuming there are actually records of totalRecords size although in reality they are not present on page, only the records that are displayed on the current page exist.
Note that, the implementation of checkbox selection in lazy mode needs to be handled manually as in this example since the DataTable cannot know about the whole dataset.
Set the loading property to display a mask layer over the table while data is being fetched. The overlay content can be customized with the loading slot.
Render placeholder rows filled with Skeleton elements while the request is in flight.
Custom empty state when no data is available, using the empty template.
Product | Category | Price | Status |
|---|
Columns can be defined dynamically using the v-for directive.
Custom content at header, body and footer sections are supported via templating.
Particular rows and cells can be styled based on conditions. The rowClass receives a row data as a parameter to return a style class for a row whereas cells are customized using the body template.
Virtual Scrolling is an efficient way to render large amount data. Usage is similar to regular scrolling with the addition of virtualScrollerOptions property to define a fixed itemSize. Internally, VirtualScroller component is utilized so refer to the API of VirtualScroller for more information about the available options.
In this example, 10000 preloaded records are rendered by the Table.
VirtualScroller is a performance-approach to handle huge data efficiently. Setting lazy on virtualScrollerOptions and providing an itemSize in pixels would be enough to enable this functionality. It is also suggested to use the same itemSize value on the row height inside the body template.
In sample below, an in-memory list and timeout is used to mimic fetching from a remote datasource. The virtualCars is an empty array that is populated on scroll.
DataTable has exclusive integration with ContextMenu using the contextMenu property to attach a menu, the row-contextmenu event to display the menu whenever a row is right clicked and the contextMenuSelection property to get a hold of the right clicked row.
Stateful table allows keeping the state such as page, sort and filtering either at local storage or session storage so that when the page is visited again, table would render the data using the last settings.
Change the state of the table e.g paginate, navigate away and then return to this table again to test this feature, the setting is set as session with the stateStorage property so that Table retains the state until the browser is closed. Other alternative is local referring to localStorage for an extended lifetime.
Sorting, per-column and global filtering, and cell editing composed in a single table.
A spreadsheet-style table editor composed from DataTable, Menu, Checkbox, Drawer and Select: typed column headers with a per-column menu (sort, copy, edit, freeze, delete), select-all and per-row checkboxes, a global filter, in-place cell editing, frozen columns, an empty-table state, plus working insert-row and add/edit-column flows that open a side drawer.
idint8 | created_attimestamptz | emailtext | plantext | ||
|---|---|---|---|---|---|
| 1 | 2026-01-01 09:10:40+00 | [email protected] | free | ||
| 2 | 2026-02-02 09:11:41+00 | [email protected] | pro | ||
| 3 | 2026-03-03 09:12:42+00 | [email protected] | team | ||
| 4 | 2026-04-04 09:13:43+00 | [email protected] | free | ||
| 5 | 2026-05-05 09:14:44+00 | [email protected] | pro | ||
| 6 | 2026-06-06 09:15:45+00 | [email protected] | team | ||
| 7 | 2026-07-07 09:10:46+00 | [email protected] | free | ||
| 8 | 2026-08-08 09:11:47+00 | [email protected] | pro | ||
| 9 | 2026-09-09 09:12:48+00 | [email protected] | team | ||
| 10 | 2026-10-10 09:13:40+00 | [email protected] | free |
DataTable uses a table element whose attributes can be extended with the tableProps option. This property allows passing aria roles and attributes like aria-label and aria-describedby to define the table for readers. Default role of the table is table. Header, body and footer elements use rowgroup, rows use row role, header cells have columnheader and body cells use cell roles. Sortable headers utilizer aria-sort attribute either set to "ascending" or "descending".
Built-in checkbox and radiobutton components for row selection use checkbox and radiobutton. The label to describe them is retrieved from the aria.selectRow and aria.unselectRow properties of the locale API. Similarly header checkbox uses selectAll and unselectAll keys. When a row is selected, aria-selected is set to true on a row.
The element to expand or collapse a row is a button with aria-expanded and aria-controls properties. Value to describe the buttons is derived from aria.expandRow and aria.collapseRow properties of the locale API.
The filter menu button use aria.showFilterMenu and aria.hideFilterMenu properties as aria-label in addition to the aria-haspopup, aria-expanded and aria-controls to define the relation between the button and the overlay. Popup menu has dialog role with aria-modal as focus is kept within the overlay. The operator dropdown use aria.filterOperator and filter constraints dropdown use aria.filterConstraint properties. Buttons to add rules on the other hand utilize aria.addRule and aria.removeRule properties. The footer buttons similarly use aria.clear and aria.apply properties. filterInputProps of the Column component can be used to define aria labels for the built-in filter components, if a custom component is used with templating you also may define your own aria labels as well.
Editable cells use custom templating so you need to manage aria roles and attributes manually if required. The row editor controls are button elements with aria.editRow, aria.cancelEdit and aria.saveEdit used for the aria-label.
Paginator is a standalone component used inside the DataTable, refer to the paginator for more information about the accessibility features.
Any button element inside the DataTable used for cases like filter, row expansion, edit are tabbable and can be used with space and enter keys.
| Key | Function |
|---|---|
| tab | Moves through the headers. |
| enter | Sorts the column. |
| space | Sorts the column. |
| Key | Function |
|---|---|
| tab | Moves through the elements inside the popup. |
| escape | Hides the popup. |
| enter | Opens the popup. |
| Key | Function |
|---|---|
| tab | Moves focus to the first selected row, if there is none then first row receives the focus. |
| up arrow | Moves focus to the previous row. |
| down arrow | Moves focus to the next row. |
| enter | Toggles the selected state of the focused row depending on the metaKeySelection setting. |
| space | Toggles the selected state of the focused row depending on the metaKeySelection setting. |
| home | Moves focus to the first row. |
| end | Moves focus to the last row. |
| shift + down arrow | Moves focus to the next row and toggles the selection state. |
| shift + up arrow | Moves focus to the previous row and toggles the selection state. |
| shift + space | Selects the rows between the most recently selected row and the focused row. |
| control + shift + home | Selects the focused rows and all the options up to the first one. |
| control + shift + end | Selects the focused rows and all the options down to the last one. |
| control + a | Selects all rows. |