DataTable
A Neo-Brutalist data table component providing comprehensive sorting, filtering, multi-selection, pagination, and virtual scrolling functionality. Supports generic data sources with flexible data presentation through columns-driven column configuration.
Demo
姓名 | 邮箱 | 角色 | 状态 | |
|---|---|---|---|---|
| 张三 | zhangsan@example.com | 管理员 | 活跃 | |
| 李四 | lisi@example.com | 编辑 | 活跃 | |
| 王五 | wangwu@example.com | 查看者 | 未活跃 | |
| 赵六 | zhaoliu@example.com | 编辑 | 活跃 | |
| 孙七 | sunqi@example.com | 管理员 | 未活跃 |
Installation
pnpm dlx brutx-vue@latest add data-tableUsage
Basic Usage
<script setup lang="ts">
import { ref } from 'vue'
import { DataTable } from 'brutx-ui-vue'
import type { DataTableColumn } from 'brutx-ui-vue'
interface User {
id: number
name: string
email: string
role: string
status: string
}
const columns: DataTableColumn<User>[] = [
{
id: 'name',
header: 'Name',
accessorKey: 'name',
sortable: true,
},
{
id: 'email',
header: 'Email',
accessorKey: 'email',
sortable: true,
},
{
id: 'role',
header: 'Role',
accessorKey: 'role',
},
{
id: 'status',
header: 'Status',
accessorKey: 'status',
align: 'center',
},
]
const data = ref<User[]>([
{ id: 1, name: 'John', email: 'john@example.com', role: 'Admin', status: 'Active' },
{ id: 2, name: 'Jane', email: 'jane@example.com', role: 'Editor', status: 'Active' },
{ id: 3, name: 'Bob', email: 'bob@example.com', role: 'Guest', status: 'Inactive' },
])
</script>
<template>
<DataTable
:data="data"
:columns="columns"
:sortable="true"
row-key="id"
/>
</template>Enabling Sorting
<template>
<DataTable
:data="data"
:columns="columns"
:sortable="true"
row-key="id"
@sort="handleSort"
/>
</template>Enable sorting via the sortable prop. Set sortable: false in column definitions to disable sorting for specific columns. Clicking the header toggles between ascending / descending / default.
Enabling Filtering
<template>
<DataTable
:data="data"
:columns="columns"
:filterable="true"
row-key="id"
@filter="handleFilter"
/>
</template>Enabling filterable displays a global search input above the table, performing fuzzy matching across all visible columns.
Enabling Selection
<template>
<DataTable
:data="data"
:columns="columns"
:selectable="true"
row-key="id"
@select="handleSelect"
/>
</template>Enabling selectable displays checkboxes on the left side of each row. The header checkbox supports select all / deselect all. When rows are selected, the bottom displays the count of selected rows with CSV export capability.
Enabling Pagination
<template>
<DataTable
:data="data"
:columns="columns"
:paginated="true"
:page-size="10"
:page-size-options="[10, 20, 50]"
row-key="id"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
/>
</template>The paginator includes first page, previous page, next page, last page buttons, and a page size selector.
Column Filters
Supports adding a Popover filter in the header of each column. Supports text search, single selection (Select), multi-selection (Multi-Select), and date range (Date Range) filtering.
date-range filters parse YYYY-MM-DD cell strings as local calendar dates and include the end date through 23:59:59.999 for that local day. Full datetime strings still use native Date / ISO datetime semantics; if your data must compare consistently across time zones, store values as Date, timestamps, or full ISO strings with explicit offsets.
<script setup lang="ts">
const columns = [
{ id: 'name', header: 'Name', accessorKey: 'name', filterType: 'text' },
{
id: 'role',
header: 'Role',
accessorKey: 'role',
filterType: 'select',
filterOptions: [
{ label: 'Admin', value: 'Admin' },
{ label: 'Editor', value: 'Editor' }
]
},
{
id: 'status',
header: 'Status',
accessorKey: 'status',
filterType: 'multi-select',
filterOptions: [
{ label: 'Active', value: 'Active' },
{ label: 'Inactive', value: 'Inactive' }
]
},
{
id: 'date',
header: 'Hire Date',
accessorKey: 'date',
filterType: 'date-range'
}
]
</script>
<template>
<DataTable
:data="data"
:columns="columns"
:filterable="true"
row-key="id"
/>
</template>Custom Cell Rendering
<script setup lang="ts">
import { h } from 'vue'
import { Badge } from 'brutx-ui-vue'
import type { DataTableColumn } from 'brutx-ui-vue'
const columns: DataTableColumn<User>[] = [
{ id: 'name', header: 'Name', accessorKey: 'name' },
{
id: 'status',
header: 'Status',
accessorKey: 'status',
cell: ({ value }) => {
return h(Badge, { variant: value === 'Active' ? 'success' : 'danger' }, () => String(value))
},
},
]
</script>The cell function enables custom cell rendering, supporting VNode or string return values. You can also use named slots #cell-{columnId} for rendering.
Using Slots
<template>
<DataTable
:data="data"
:columns="columns"
row-key="id"
>
<template #cell-status="{ row, value }">
<Badge :variant="value === 'Active' ? 'success' : 'danger'">
{{ value }}
</Badge>
</template>
<template #toolbar>
<Button variant="primary" size="sm">
Add User
</Button>
</template>
<template #empty>
<div class="text-center py-8">
<p class="text-lg font-bold">No Data</p>
<p class="text-sm text-brutal-fg/60">Click the button above to add your first record</p>
</div>
</template>
</DataTable>
</template>Loading State
<template>
<DataTable
:data="data"
:columns="columns"
:loading="isLoading"
row-key="id"
/>
</template>When loading is true, a spinning loader overlay appears above the table. You can also customize loading content via the loading named slot.
Sizes
<template>
<!-- Small size + compact density, ideal for information-dense tables -->
<DataTable
:data="data"
:columns="columns"
:sortable="true"
size="sm"
:dense="true"
row-key="id"
/>
<!-- Large size, ideal for display-oriented tables -->
<DataTable
:data="data"
:columns="columns"
size="lg"
row-key="id"
/>
</template>size controls font size and vertical cell padding (sm -> py-2, default -> py-3, lg -> py-4); dense further compresses row height to py-1.5, orthogonal to size, and can be used independently or in combination.
Stripe Control
<template>
<!-- Stripes enabled by default (even rows bg-brutal-muted/50) -->
<DataTable
:data="data"
:columns="columns"
row-key="id"
/>
<!-- Explicitly disable stripes -->
<DataTable
:data="data"
:columns="columns"
:striped="false"
row-key="id"
/>
</template>striped defaults to true, applying bg-brutal-muted/50 to even rows for alternating row colors. Set to false for a clean appearance or when using custom row backgrounds.
Sticky Header
<template>
<DataTable
:data="largeData"
:columns="columns"
:sticky-header="true"
row-key="id"
/>
</template>When stickyHeader is enabled, the header stays at the top of the visible area while the page or an outer vertical scroll container moves. The header follows the body during horizontal scrolling; virtual rows keep their own vertical scroll area.
Data Types
DataTableColumn
| Field | Type | Description |
|---|---|---|
id | string | Column unique identifier, required |
header | string | ((ctx: DataTableColumnHeaderContext) => string) | Column header, required; function form receives DataTableColumnHeaderContext context |
accessorKey | keyof T & string | Access row data field by key |
accessorFn | (row: T) => unknown | Access row data value by function |
cell | (props: { row: T; value: unknown }) => VNode | string | Custom cell rendering |
sortable | boolean | Whether sortable, defaults to true |
hidden | boolean | Whether hidden |
width | number | 'auto' | Column width |
minWidth | number | Minimum width |
maxWidth | number | Maximum width |
align | 'left' | 'center' | 'right' | Alignment |
filterType | 'text' | 'select' | 'multi-select' | 'date-range' | Filter type, displays corresponding filter popover in column header |
filterOptions | Array<{ label: string; value: any }> | Filter options, used for select and multi-select filters |
DataTableColumnHeaderContext
Context object received by the header callback function, used to access the column's runtime state in functional headers.
| Field | Type | Description |
|---|---|---|
id | string | Current column ID |
sortable | boolean | Whether the current column is sortable |
direction | 'asc' | 'desc' | null | Current column sort direction (null means unsorted) |
accessorKey | PropertyKey | Current column's accessorKey (if any) |
align | 'left' | 'center' | 'right' | Current column's alignment |
DataTableVirtualScroll
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | — | Whether to enable virtual scrolling |
rowHeight | number | 'auto' | 48 | Estimated row height (pixels), 'auto' to observe and measure dynamic height via DOM (requires all columns to have explicit width configuration) |
DataTableFilterState
| Field | Type | Description |
|---|---|---|
global | string | Global filter keyword |
columns | Record<string, any> | Column-level filter values indexed by column ID |
Programmatic Control
DataTable exposes sorting, filtering, selection, and pagination methods and state via defineExpose. These can be called directly from the parent component through a component ref, enabling scenarios like "external toolbars", "external sort triggers", and "batch operation buttons".
<script setup lang="ts">
import { ref } from 'vue'
import { DataTable, Button } from 'brutx-ui-vue'
import type { DataTableColumn } from 'brutx-ui-vue'
interface User {
id: number
name: string
email: string
role: string
status: string
}
const tableRef = ref<InstanceType<typeof DataTable> | null>(null)
const columns: DataTableColumn<User>[] = [
{ id: 'name', header: 'Name', accessorKey: 'name', sortable: true },
{ id: 'email', header: 'Email', accessorKey: 'email' },
{ id: 'role', header: 'Role', accessorKey: 'role' },
{ id: 'status', header: 'Status', accessorKey: 'status' },
]
const data: User[] = [
{ id: 1, name: 'John', email: 'john@example.com', role: 'Admin', status: 'Active' },
{ id: 2, name: 'Jane', email: 'jane@example.com', role: 'Editor', status: 'Inactive' },
{ id: 3, name: 'Bob', email: 'bob@example.com', role: 'Guest', status: 'Active' },
]
// Programmatically sort by name ascending
function sortByNameAsc() {
tableRef.value?.sort.toggleSort('name')
}
// Programmatically set global filter keyword
function filterByAdmin() {
tableRef.value?.filter.setGlobalFilter('Admin')
}
// Select all on current page
function selectAll() {
tableRef.value?.selection.toggleAllRows()
}
// Go to next page
function goNextPage() {
tableRef.value?.pagination.nextPage()
}
</script>
<template>
<div class="flex flex-wrap items-center gap-2 mb-4">
<Button variant="primary" size="sm" @click="sortByNameAsc">Sort by Name</Button>
<Button variant="default" size="sm" @click="filterByAdmin">Filter "Admin"</Button>
<Button variant="default" size="sm" @click="selectAll">Select All on Page</Button>
<Button variant="default" size="sm" @click="goNextPage">Next Page</Button>
</div>
<DataTable
ref="tableRef"
:data="data"
:columns="columns"
:sortable="true"
:filterable="true"
:selectable="true"
:paginated="true"
:page-size="2"
row-key="id"
/>
</template>Exposed Members
A component ref provides sorting, filtering, selection, pagination, and row-expansion namespaces and their state. See the API reference below for every exposed member. Programmatic sort.toggleSort and selection state mutations do not emit sort or select; filter state changes still emit filter; pagination methods do not emit page-change or page-size-change; expand.toggleRow emits expand-change.
API Reference
DataTable
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | — | Custom CSS classes added to the table root container. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
dataRequired | T[] | — | The rows to display. Generic type T is carried through column definitions, row events, and the programmatic API. |
DetailsDeclared typeT[] Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
columnsRequired | DataTableColumn<T>[] | — | The column definitions that control headers, value access, sorting, filtering, rendering, and column layout. |
DetailsDeclared typeDataTableColumn<T>[] Referenced types DataTableColumn Type definition — DataTableColumnexport interface DataTableColumn<T extends object = Record<string, unknown>> {
id: string
/** 函数签名已更新:回调参数从 DataTableColumn<T> 改为 DataTableColumnHeaderContext */
header: string | ((ctx: DataTableColumnHeaderContext) => string)
accessorKey?: keyof T & string
accessorFn?: (row: T) => unknown
cell?: (props: { row: T; value: unknown }) => VNode | string
sortable?: boolean
hidden?: boolean
width?: number | 'auto'
minWidth?: number
maxWidth?: number
align?: 'left' | 'center' | 'right'
/** 固定列方向 */
fixed?: 'left' | 'right'
/** 列类型 */
type?: 'default' | 'expand'
/** 过滤器类型 */
filterType?: 'text' | 'select' | 'multi-select' | 'date-range'
/** 过滤可选项 */
filterOptions?: Array<{ label: string; value: string | number }>
}Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
sortable | boolean | undefined | false | Enables sortable-column header interaction and sorted data; an individual column can opt out with sortable: false. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
filterable | boolean | undefined | false | Shows the global search input and column filters for columns that declare filterType. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
filterPlaceholder | string | undefined | undefined | The global search input placeholder and accessible name; when omitted, the localized dataTable.filterPlaceholder message is used. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
selectable | boolean | undefined | false | Shows row checkboxes and a select-all checkbox, and enables reading and exporting selected rows. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
paginated | boolean | undefined | false | Enables page slicing and the pagination controls. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
pageSize | number | undefined | 10 | The number of rows per page when pagination is enabled; data is not sliced into pages when pagination is disabled. |
DetailsDeclared typenumber | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
pageSizeOptions | number[] | undefined | [10, 20, 50, 100]Factory evaluated per instance | The page sizes offered by the pagination control. |
DetailsDeclared typenumber[] | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
loading | boolean | undefined | false | Displays the loading overlay and the loading slot content. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
emptyMessage | string | undefined | — | The empty-state message; when omitted or empty, the localized dataTable.noData message is used. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
rowKeyRequired | keyof T | ((row: T) => string | number) | — | Provides a unique row-key field or accessor; row selection and expansion rely on the resolved string or number key. |
DetailsDeclared typekeyof T | ((row: T) => string | number) Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
rowClickable | boolean | undefined | false | Makes a row activate the row-click event through pointer click or the Enter key. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
title | string | undefined | undefined | The heading shown above the table when the header slot is not supplied. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
description | string | undefined | undefined | The supporting text shown below the heading when the header slot is not supplied. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
section | boolean | undefined | false | Applies a constrained width and centered layout to the table root container. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
framed | boolean | undefined | true | Controls the root border, shadow, and rounded corners; false removes those frame styles. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
virtualScroll | DataTableVirtualScroll | undefined | — | Configures row virtualization. It is enabled when enabled is true; rowHeight can be fixed or measured dynamically with auto. |
DetailsDeclared typeDataTableVirtualScroll | undefined Referenced types DataTableVirtualScroll Type definition — DataTableVirtualScrollexport interface DataTableVirtualScroll {
enabled?: boolean
rowHeight?: number | 'auto'
}Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
size | "default" | "lg" | "sm" | undefined | "default" | Sets the table size variant. |
DetailsDeclared type"default" | "lg" | "sm" | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
dense | boolean | undefined | false | Uses more compact row and cell spacing. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
striped | boolean | undefined | true | Controls alternating background stripes on data rows. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
stickyHeader | boolean | undefined | false | Keeps the header at the top of the visible area during page or outer-container vertical scrolling and synchronizes it with horizontal body scrolling. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
expandable | boolean | undefined | false | Shows row expansion controls and allows the expanded-row slot to render. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
expandRowKeys | Set<string | number> | undefined | undefined | The controlled set of expanded row keys. Keys must match rowKey resolution, and changes synchronize the internal expansion state. |
DetailsDeclared typeSet<string | number> | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
spanMethod | ((params: DataTableSpanMethodParams<T>) => void | [number, number]) | undefined | undefined | Calculates a merge span for each displayed row and visible column. Return rowspan and colspan, or nothing to use the default span. |
DetailsDeclared type((params: DataTableSpanMethodParams<T>) => void | [number, number]) | undefined Default value details
Sourcepackages/ui/src/types/data-table.ts | |||
| Name | Signature or type | Description |
|---|---|---|
@sort | [column: string, direction: "asc" | "desc" | null] | Emits the column ID and direction after the user interacts with a sortable header; direction is asc, desc, or null. |
DetailsDeclared type[column: string, direction: "asc" | "desc" | null] Literal values
Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@filter | [filters: DataTableFilterState] | Emits the current global and column filter state when filtering changes. |
DetailsDeclared type[filters: DataTableFilterState] Referenced types DataTableFilterState Type definition — DataTableFilterStateexport interface DataTableFilterState {
global?: string
columns: Record<string, DataTableFilterValue>
}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@select | [rows: T[]] | Emits the selected row data array after the user toggles a row or the current-page select-all control. |
DetailsDeclared type[rows: T[]] Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@page-change | [page: number] | Emits the page number after user navigation changes the current page; no event is emitted when the page stays the same. |
DetailsDeclared type[page: number] Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@page-size-change | [size: number] | Emits the new page size after the user selects it in the pagination control. |
DetailsDeclared type[size: number] Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@expand-change | [row: T, expanded: boolean] | Emits the row data and its new expanded boolean when the row expansion state toggles. |
DetailsDeclared type[row: T, expanded: boolean] Literal values
Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@row-click | [row: T] | When rowClickable is enabled, emits row data after a pointer click or Enter activation; events originating inside buttons, inputs, links, or other interactive elements are ignored. |
DetailsDeclared type[row: T] Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
@export | [format: "csv" | "json", selectedRows?: T[] | undefined] | Emits the selected format and current selected-row array when a table export control is activated. |
DetailsDeclared type[format: "csv" | "json", selectedRows?: T[] | undefined] Literal values
Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
| Name | Signature or type | Description |
|---|---|---|
#header | {} | Replaces the default table header; when omitted, the heading area is rendered from title and description. |
DetailsDeclared type{}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
#toolbar | {} | Additional content for the global filtering toolbar; when filterable is enabled, it appears beside the search input. |
DetailsDeclared type{}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
#expanded-row | { row: T; index: number; } | Additional expanded-row content with row and its index in the displayed list; rendered only for an expanded row when expandable is enabled. |
DetailsDeclared type{ row: T; index: number; }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
#empty | {} | Replaces the empty-state content; rendered only when there is no display data and loading is false. |
DetailsDeclared type{}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
#loading | {} | Replaces the loading overlay content; rendered only when loading is true. |
DetailsDeclared type{}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
#footer | {} | Additional footer content rendered after the table and loading area. |
#cell-{columnId} | { row: T; value: unknown } | Provides custom content for a column cell. Use the cell-{columnId} slot name; its scope exposes the current row and cell value.
|
DetailsDeclared type{ row: T; value: unknown }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
| Name | Signature or type | Description |
|---|---|---|
sort | { toggleSort: (columnId: string) => void; sortState: Readonly<Ref<{ readonly column: string; readonly direction: "asc" | "desc" | null; }, { readonly column: string; readonly direction: "asc" | "desc" | null; }>>; } | The table sorting namespace, containing toggleSort and the read-only sortState. |
DetailsDeclared type{ toggleSort: (columnId: string) => void; sortState: Readonly<Ref<{ readonly column: string; readonly direction: "asc" | "desc" | null; }, { readonly column: string; readonly direction: "asc" | "desc" | null; }>>; }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
sort.toggleSort | (columnId: string) => void | Toggles sorting for a column ID. Sorting must be enabled and the column must not opt out; the cycle is ascending, descending, then cleared. |
DetailsDeclared type(columnId: string) => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
sort.sortStateReadonly | Readonly<Ref<{ readonly column: string; readonly direction: "asc" | "desc" | null; }, { readonly column: string; readonly direction: "asc" | "desc" | null; }>> | The read-only reactive sort state containing the current column ID and asc, desc, or null direction. |
DetailsDeclared typeReadonly<Ref<{ readonly column: string; readonly direction: "asc" | "desc" | null; }, { readonly column: string; readonly direction: "asc" | "desc" | null; }>>Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
filter | { filterState: Readonly<Ref<{ readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }, { readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }>>; setGlobalFilter: (value: string) => void; setFilterState: (state: DataTableFilterState) => void; } | The table filtering namespace, providing state access and methods to set global or complete filter criteria. |
DetailsDeclared type{ filterState: Readonly<Ref<{ readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }, { readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }>>; setGlobalFilter: (value: string) => void; setFilterState: (state: DataTableFilterState) => void; }Referenced types DataTableFilterState Type definition — DataTableFilterStateexport interface DataTableFilterState {
global?: string
columns: Record<string, DataTableFilterValue>
}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
filter.filterStateReadonly | Readonly<Ref<{ readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }, { readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }>> | The read-only reactive filter state, with an optional global value and columns indexed by column ID. |
DetailsDeclared typeReadonly<Ref<{ readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }, { readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }>>Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
filter.setGlobalFilter | (value: string) => void | Sets the global search keyword. |
DetailsDeclared type(value: string) => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
filter.setFilterState | (state: DataTableFilterState) => void | Replaces the complete filtering state with the supplied DataTableFilterState. |
DetailsDeclared type(state: DataTableFilterState) => void Referenced types DataTableFilterState Type definition — DataTableFilterStateexport interface DataTableFilterState {
global?: string
columns: Record<string, DataTableFilterValue>
}Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection | { toggleRow: (row: T) => void; toggleAllRows: () => void; clearSelection: () => void; getSelectedRows: () => T[]; selectedRows: Readonly<ShallowRef<ReadonlySet<string | number>>>; isAllSelected: ComputedRef<boolean>; } | The table selection namespace, providing row-selection actions, selected-key state, and a method to read selected row data. |
DetailsDeclared type{ toggleRow: (row: T) => void; toggleAllRows: () => void; clearSelection: () => void; getSelectedRows: () => T[]; selectedRows: Readonly<ShallowRef<ReadonlySet<string | number>>>; isAllSelected: ComputedRef<boolean>; }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.toggleRow | (row: T) => void | Toggles selection for the specified row; selectable must be enabled. |
DetailsDeclared type(row: T) => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.toggleAllRows | () => void | Toggles selection for all rows on the current display page; clearing preserves selections from other pages or filtered-out rows. |
DetailsDeclared type() => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.clearSelection | () => void | Clears all selected row keys. |
DetailsDeclared type() => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.getSelectedRows | () => T[] | Returns the full row data array for the current selection. |
DetailsDeclared type() => T[] Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.selectedRowsReadonly | Readonly<ShallowRef<ReadonlySet<string | number>>> | The read-only shallow-reactive set of selected row keys. |
DetailsDeclared typeReadonly<ShallowRef<ReadonlySet<string | number>>> Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
selection.isAllSelectedReadonly | ComputedRef<boolean> | A read-only computed state indicating whether all rows on the current display page are selected. |
DetailsDeclared typeComputedRef<boolean> Literal values
Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination | { goToPage: (page: number) => boolean; nextPage: () => boolean; previousPage: () => boolean; setPageSize: (size: number) => void; pageIndex: Readonly<Ref<number, number>>; pageCount: ComputedRef<number>; } | The table pagination namespace, containing page state and pagination control methods. |
DetailsDeclared type{ goToPage: (page: number) => boolean; nextPage: () => boolean; previousPage: () => boolean; setPageSize: (size: number) => void; pageIndex: Readonly<Ref<number, number>>; pageCount: ComputedRef<number>; }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.goToPage | (page: number) => boolean | Navigates to the requested page, clamps it to the valid range, and returns whether the page changed. |
DetailsDeclared type(page: number) => boolean Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.nextPage | () => boolean | Attempts to move to the next page and returns whether the page changed. |
DetailsDeclared type() => boolean Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.previousPage | () => boolean | Attempts to move to the previous page and returns whether the page changed. |
DetailsDeclared type() => boolean Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.setPageSize | (size: number) => void | Sets the page size and resets the current page to the first page; invalid sizes are ignored. |
DetailsDeclared type(size: number) => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.pageIndexReadonly | Readonly<Ref<number, number>> | The read-only reactive current page number, starting at 1. |
DetailsDeclared typeReadonly<Ref<number, number>> Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
pagination.pageCountReadonly | ComputedRef<number> | The read-only computed page count; it is at least 1 when there are no rows. |
DetailsDeclared typeComputedRef<number> Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
expand | { toggleRow: (row: T) => void; isRowExpanded: (row: T) => boolean; expandedRowKeys: ShallowRef<Set<string | number>, Set<string | number>>; } | The table row-expansion namespace, providing toggle and query methods plus the expanded-key state. |
DetailsDeclared type{ toggleRow: (row: T) => void; isRowExpanded: (row: T) => boolean; expandedRowKeys: ShallowRef<Set<string | number>, Set<string | number>>; }Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
expand.toggleRow | (row: T) => void | Toggles expansion for the specified row and emits expand-change. |
DetailsDeclared type(row: T) => void Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
expand.isRowExpanded | (row: T) => boolean | Checks whether the specified row is currently expanded. |
DetailsDeclared type(row: T) => boolean Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
expand.expandedRowKeys | ShallowRef<Set<string | number>, Set<string | number>> | The shallow-reactive set containing the currently expanded row keys. |
DetailsDeclared typeShallowRef<Set<string | number>, Set<string | number>> Sourcepackages/ui/src/components/data-table/DataTable.vue | ||
DataTableColumnFilter
| Name | Type | Default | Description |
|---|---|---|---|
columnRequired | DataTableColumn<any> | — | The column definition for this filter control; its filterType and filterOptions determine the filter UI. |
DetailsDeclared typeDataTableColumn<any> Referenced types DataTableColumn Type definition — DataTableColumnexport interface DataTableColumn<T extends object = Record<string, unknown>> {
id: string
/** 函数签名已更新:回调参数从 DataTableColumn<T> 改为 DataTableColumnHeaderContext */
header: string | ((ctx: DataTableColumnHeaderContext) => string)
accessorKey?: keyof T & string
accessorFn?: (row: T) => unknown
cell?: (props: { row: T; value: unknown }) => VNode | string
sortable?: boolean
hidden?: boolean
width?: number | 'auto'
minWidth?: number
maxWidth?: number
align?: 'left' | 'center' | 'right'
/** 固定列方向 */
fixed?: 'left' | 'right'
/** 列类型 */
type?: 'default' | 'expand'
/** 过滤器类型 */
filterType?: 'text' | 'select' | 'multi-select' | 'date-range'
/** 过滤可选项 */
filterOptions?: Array<{ label: string; value: string | number }>
}Default value details
Sourcepackages/ui/src/components/data-table/DataTableColumnFilter.vue | |||
filterStateRequired | { readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; } | — | The current read-only filter state, used to display this column’s text, option, or date-range value. |
DetailsDeclared type{ readonly global?: string | undefined; readonly columns: { readonly [x: string]: string | number | readonly (string | number)[] | { readonly start: string | null; readonly end: string | null; } | null | undefined; }; }Default value details
Sourcepackages/ui/src/components/data-table/DataTableColumnFilter.vue | |||
headerLabelRequired | string | — | The displayed column-header text used to label the filter control. |
DetailsDeclared typestring Default value details
Sourcepackages/ui/src/components/data-table/DataTableColumnFilter.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@update:filterState | [state: DataTableFilterState] | Emits a state object containing only the current column change when its filter value changes; a null column value clears that column filter. |
DetailsDeclared type[state: DataTableFilterState] Referenced types DataTableFilterState Type definition — DataTableFilterStateexport interface DataTableFilterState {
global?: string
columns: Record<string, DataTableFilterValue>
}Sourcepackages/ui/src/components/data-table/DataTableColumnFilter.vue | ||
DataTableColumn Type
DataTableColumn Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — (required) | Column unique identifier |
header | string | ((ctx) => string) | — (required) | Column header text or render function |
accessorKey | keyof T & string | — | Data field key |
accessorFn | (row: T) => unknown | — | Custom value accessor function |
cell | (props) => VNode | string | — | Custom cell render function |
sortable | boolean | — | Whether the column is sortable |
hidden | boolean | — | Whether to hide the column |
width | number | 'auto' | — | Column width |
minWidth | number | — | Minimum column width |
maxWidth | number | — | Maximum column width |
align | 'left' | 'center' | 'right' | — | Column content alignment |
fixed | 'left' | 'right' | — | Fixed column direction; offsets use the browser-rendered width. Set width when a stable width is needed. |
type | 'default' | 'expand' | 'default' | Column type (expand for expand column) |
Accessibility
The DataTable component follows the WAI-ARIA table pattern, providing the following accessibility support:
- Uses semantic
<table>,<thead>,<tbody>,<tr>,<th>,<td>elements - Sort state communicated to screen readers via
aria-sortattribute - Selection state marked via
aria-selectedattribute on selected rows - Filter inputs and pagination controls provide appropriate
aria-label - Keyboard navigation support: Tab key switches between interactive elements, Enter/Space triggers sorting and selection
FAQ
Q: Why isn't the selection state working after setting selectable?
A: Ensure the row-key prop is correctly set. row-key identifies the uniqueness of each row, and the selection feature depends on it to track selected rows. If row-key is not provided, selection will not work properly. It is recommended to use a unique field from the data, such as id.
Q: What is the execution order when sorting, filtering, and pagination are all enabled?
A: The component processes data internally in the order: "filter -> sort -> paginate". That is, data is first filtered by filter criteria, then sorted, and finally paginated. If programmatic APIs (like setGlobalFilter and toggleSort) are used simultaneously, the same processing order applies.
Q: How do I optimize table performance with large datasets?
A: When the data exceeds several hundred rows, it is recommended to enable virtual scrolling. By configuring :virtual-scroll="{ enabled: true }", the table will only render rows within the visible area, significantly reducing DOM node count. You can also set :dense="true" to compress row height, further improving information density within the visible area.