Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Accessibility
Vuetify

Sign in

Sign in with your preferred provider to access your account.

createDataTable

A composable data table that composes v0 primitives into a complete data pipeline with sorting, filtering, pagination, selection, expansion, and grouping.


Advanced96.4% coverageBlazing FastFeb 18, 2026

Usage

Pass items and columns to get a fully reactive data table with search, sort, and pagination ready to use.

ts
import { createDataTable } from '@vuetify/v0'

const table = createDataTable({
  items: users,
  columns: [
    { key: 'name', title: 'Name', sortable: true, filterable: true },
    { key: 'email', title: 'Email', sortable: true, filterable: true },
    { key: 'role', title: 'Role', sortable: true },
  ],
})

// Search
table.search('john')
console.log(table.query.value) // 'john'

// Sort — toggle cycles: none → asc → desc → none
table.sort.toggle('name')

// Paginate
table.pagination.next()

// Select rows
table.selection.toggle('user-1')
Name Email Role
Alice Johnsonalice@example.comAdmin
Bob Smithbob@example.comEditor
Carol Daviscarol@example.comViewer
Dan Wilsondan@example.comEditor
Eve Martinezeve@example.comAdmin
8 total
1 / 2

Adapters

Adapters control the data pipeline strategy. Pass one via the adapter option.

AdapterPipelineUse Case
ClientAdapterfilter → sort → paginateDefault. All processing client-side
ServerAdapterpass-throughAPI-driven. Server handles filter/sort/paginate
VirtualAdapterfilter → sort → (no paginate)Large lists rendered with createVirtual

ClientAdapter (default)

All processing happens client-side. No constructor options — just use createDataTable without an adapter option.

Diagram

Use controls to zoom and pan. Click outside or press Escape to close.

Behavior:

  • Resets to page 1 on filter or sort changes

  • total reflects the sorted item count

  • No loading or error state (synchronous pipeline)

ts
import { createDataTable, ClientAdapter } from '@vuetify/v0'

const table = createDataTable({
  items: users,
  columns,
  adapter: new ClientAdapter(), // default — not required
})

ServerAdapter

Pass-through adapter for API-driven tables. The server handles all filtering, sorting, and pagination — the client only renders what it receives.

Diagram

Use controls to zoom and pan. Click outside or press Escape to close.

Constructor options:

OptionTypeRequiredDescription
totalMaybeRefOrGetter<number>YesTotal item count on the server (drives pagination)
loadingMaybeRefOrGetter<boolean>NoLoading state (e.g., from useFetch)
errorMaybeRefOrGetter<Error | null>NoError state from API calls

Behavior:

  • Resets to page 1 on filter or sort changes

  • allItems, filteredItems, sortedItems, and items all point to the same source (no client-side processing)

  • Exposes loading and error via table.loading and table.error

ts
import { createDataTable, ServerAdapter } from '@vuetify/v0'

const table = createDataTable({
  items: serverItems,
  columns,
  adapter: new ServerAdapter({
    total: totalCount,
    loading: isLoading,
    error: fetchError,
  }),
})

// Watch query/sort/page to trigger API calls
watch(
  [table.query, table.sort.columns, table.pagination.page],
  () => fetchData()
)

VirtualAdapter

Client-side filtering and sorting without pagination slicing. All sorted items are returned for use with createVirtual at the rendering layer.

Diagram

Use controls to zoom and pan. Click outside or press Escape to close.

Behavior:

  • No constructor options — instantiate with new VirtualAdapter()

  • Resets on filter or sort changes

  • No loading or error state

ts
import { createDataTable, VirtualAdapter, createVirtual } from '@vuetify/v0'

const table = createDataTable({
  items: largeDataset,
  columns,
  adapter: new VirtualAdapter(),
})

// Wrap table.items with createVirtual for rendering
const virtual = createVirtual(table.items, { itemHeight: 40 })

Features

Sorting

Toggle sort cycles through directions. Configure with mandate and firstSortOrder.

ts
const table = createDataTable({
  items,
  columns: [
    { key: 'name', sortable: true },
    { key: 'age', sortable: true, sort: (a, b) => Number(a) - Number(b) },
  ],
  mandate: true,             // asc → desc → asc (never clears)
  firstSortOrder: 'desc',   // First click sorts descending
  sortMultiple: true,        // Enable multi-column sort
})

table.sort.toggle('name')
table.sort.direction('name')     // 'asc' | 'desc' | 'none'
table.sort.priority('name')      // 0-based index, or -1
table.sort.columns.value         // [{ key: 'name', direction: 'asc' }]
table.sort.order                 // ['name'] — multi-sort priority array
table.sort.reset()               // Clear all sort state

Filtering

Search filters across all filterable columns. Use per-column filter for custom logic.

ts
const table = createDataTable({
  items,
  columns: [
    { key: 'name', filterable: true },
    { key: 'status', filterable: true, filter: (value, query) => {
      return String(value).toLowerCase() === query.toLowerCase()
    }},
  ],
})

table.search('active')

Selection

Control row selection with the selectStrategy option.

StrategyBehavior
'single'Only one row selected at a time
'page'selectAll/toggleAll operate on visible page (default)
'all'selectAll/toggleAll operate on all filtered items
ts
const table = createDataTable({
  items,
  columns,
  selectStrategy: 'page',
  itemSelectable: 'canSelect',  // Disable selection for rows where canSelect is falsy
})

table.selection.toggle('row-1')
table.selection.isSelected('row-1')     // true
table.selection.isSelectable('row-1')   // true (based on itemSelectable)
table.selection.toggleAll()
table.selection.isAllSelected.value     // true
table.selection.isMixed.value           // false

Expansion

Expand rows to reveal detail content.

ts
const table = createDataTable({
  items,
  columns,
  expandMultiple: false,  // Only one row expanded at a time
})

table.expansion.toggle('row-1')
table.expansion.isExpanded('row-1')  // true
table.expansion.expandAll()
table.expansion.collapseAll()

Grouping

Group rows by a column value.

ts
const table = createDataTable({
  items,
  columns,
  groupBy: 'department',
  enroll: true,  // Auto-open all groups
})

table.grouping.groups.value  // [{ key: 'Engineering', value: 'Engineering', items: [...] }]
table.grouping.toggle('Engineering')
table.grouping.isOpen('Engineering')
table.grouping.openAll()
table.grouping.closeAll()

Reactivity

PropertyReactiveNotes
itemsComputed — final visible items
allItemsComputed — raw unprocessed items
filteredItemsComputed — items after filtering
sortedItemsComputed — items after filter + sort
queryShallowRef — current search query (readonly)
sort.columnsComputed — current sort entries
pagination.pageShallowRef — current page
pagination.itemsComputed — visible page buttons
selection.isAllSelectedComputed — all in scope selected
selection.isMixedComputed — some but not all selected
grouping.groupsComputed — grouped items
totalComputed — total row count
loadingComputed — adapter loading state
errorComputed — adapter error state

Examples

Server Adapter

A data table backed by a simulated API. The ServerAdapter delegates all filtering, sorting, and pagination to the server — the client only renders what it receives.

File breakdown:

FileRole
ServerTable.vueTable with loading state, search, sort, and pagination
columns.tsColumn definitions
api.tsSimulated server with fetchUsers() that filters/sorts/paginates a dataset

Key patterns:

  • ServerAdapter receives total and loading refs so the table knows the full dataset size without holding it client-side

  • A watch on [table.query, table.sort.columns, table.pagination.page] triggers fetchUsers() whenever the user interacts

  • The simulated API applies search, sort, and pagination server-side, returning only the current page of results

Loading...
Name Email Department
0 total
1 / 0

Grouping, Selection & Custom Sort

A grouped table with row selection, custom numeric sort, and salary range filtering. Rows with active: false cannot be selected.

File breakdown:

FileRole
FeaturesTable.vueGrouped table with checkboxes, collapsible groups, and status badges
columns.tsColumns with custom sort (numeric) and filter (range queries like >100000)
data.tsEmployee dataset with departments, salaries, and active status

Key patterns:

  • groupBy: 'department' groups rows automatically — enroll: true opens all groups on creation

  • table.grouping.isOpen(key) checks visibility, toggle(key) flips it

  • itemSelectable: 'active' disables checkboxes for inactive employees

  • mandate: true ensures a sort column is always active (never clears to unsorted)

Name Department Salary Status
Engineering (4)
Alice JohnsonEngineering$120,000Active
Bob SmithEngineering$95,000Active
Grace KimEngineering$110,000Active
Jack BrownEngineering$105,000Active
Design (2)
Carol DavisDesign$88,000Inactive
Dan WilsonDesign$92,000Active
Marketing (2)
Eve MartinezMarketing$78,000Active
Frank LeeMarketing$82,000Active
Sales (2)
Henry ChenSales$75,000Inactive
Iris ParkSales$85,000Active
0 selected of 10 total

Virtual Scrolling

A table with 1,000 rows rendered through createVirtual. The VirtualAdapter skips pagination — all filtered/sorted items are passed directly to the virtual scroller.

File breakdown:

FileRole
VirtualTable.vueVirtual-scrolled table with sticky header and sort controls
columns.tsColumn definitions with custom numeric sort for the score column
data.tsGenerator that creates 1,000 sample user records

Key patterns:

  • VirtualAdapter performs client-side filter and sort but returns all items (no pagination slicing)

  • createVirtual(table.items, { itemHeight: 40 }) handles virtualization at the rendering layer

  • The sticky <thead> stays visible while scrolling through virtual rows

  • Stats show rendered vs. filtered vs. total counts to demonstrate the virtual window

0 rendered / 1000 filtered / 1000 total
Name Email Score

API Reference

The following API details are for the createDataTable composable.

Functions

createDataTable

(options: DataTableOptions<T>) => DataTableContext<T>

Creates a data table instance with sort controls, selection, and an adapter-driven data pipeline. Must be called inside a component `setup()` or a Vue effect scope. Calling at module scope in SSR environments causes request state leakage.

createDataTableContext

(_options: DataTableContextOptions<T>) => ContextTrinity<DataTableContext<T>>

Creates a data table context with dependency injection support.

useDataTable

(namespace?: string) => DataTableContext<T>

Returns the current data table context from dependency injection.

Options

items required

MaybeRefOrGetter<T[]>

Source items

columns required

readonly DataTableColumn<T>[]

Column definitions

itemValue

KeysOfType<T, ID>

Property used as row identifier. Must resolve to a string or number value.

Default: 'id'

filter

Omit<FilterOptions, "keys">

Filter options (keys derived from columns)

pagination

Omit<PaginationOptions, "size">

Pagination options (size derived from pipeline)

sortMultiple

boolean

Enable multi-column sort.

Default: false

mandate

boolean

Prevent clearing sort (asc → desc → asc cycle).

Default: false

firstSortOrder

"asc" | "desc"

Direction for first sort click.

Default: 'asc'

selectStrategy

SelectStrategy

Selection strategy: 'single' selects one row, 'page' operates on visible items, 'all' operates on all filtered items.

Default: 'page'

itemSelectable

keyof T & string

Property that controls per-row selectability

groupBy

keyof T & string

Column key to group rows by

enroll

boolean

Auto-open all groups on creation.

Default: false

expandMultiple

boolean

Allow multiple rows expanded simultaneously.

Default: true

locale

string

Locale for sorting (defaults to useLocale's selected locale or browser default)

adapter

DataTableAdapterInterface<T>

Pipeline adapter.

Default: ClientAdapter

Properties

items

Readonly<Ref<readonly T[], readonly T[]>>

Final paginated items for rendering

allItems

Readonly<Ref<readonly T[], readonly T[]>>

Raw unprocessed items

filteredItems

Readonly<Ref<readonly T[], readonly T[]>>

Items after filtering

sortedItems

Readonly<Ref<readonly T[], readonly T[]>>

Items after filtering and sorting

columns

readonly DataTableColumn<T>[]

Column definitions

query

Readonly<ShallowRef<string>>

Current search query (readonly)

sort

DataTableSort

Sort controls

pagination

PaginationContext

Pagination controls

selection

DataTableSelection

Row selection controls

expansion

DataTableExpansion

Row expansion controls

grouping

DataTableGrouping<T>

Row grouping controls. When groupBy is not set, `groups` returns an empty array.

total

Readonly<Ref<number, number>>

Total row count for aria-rowcount

loading

Readonly<Ref<boolean, boolean>>

Loading state (managed by adapter)

error

Readonly<Ref<Error, Error>>

Error state (managed by adapter)

Methods

(value: string) => void

Set the search query

Benchmarks

Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.

View benchmark source↗

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/