Data Table
The VDataTable component is used for displaying tabular data. It includes features such as sorting, searching, pagination, row selection, expandable rows, and grouping.
<template>
<v-data-table
:headers="headers"
:items="desserts"
/>
</template>
<script setup>
const headers = [
{ title: 'Dessert', key: 'name' },
{ title: 'Calories', key: 'calories' },
{ title: 'Fat (g)', key: 'fat' },
]
const desserts = [
{ name: 'Frozen Yogurt', calories: 159, fat: 6.0 },
{ name: 'Ice cream sandwich', calories: 237, fat: 9.0 },
{ name: 'Eclair', calories: 262, fat: 16.0 },
]
</script>
Array of header definitions. Each header can have: title, key, value, sortable, align, width, minWidth, maxWidth, fixed, sort, filter
Array of data items to display in the table
itemValue
string | function
default:"id"
Property or function to use as the unique identifier for each item
Array of sort configurations. Each item has key and order (asc or desc)
Allows sorting by multiple columns
Requires at least one sort to be active
Number of items to display per page. Use -1 for all items
Shows checkboxes for row selection
Selection strategy. Options: single, page, all
Array of selected items (v-model)
Shows expand icon for expandable rows
Array of grouping configurations. Each item has key and order
loading
boolean | string
default:"false"
Shows a loading indicator. Can be a boolean or loading text
loadingText
string
default:"$vuetify.dataIterator.loadingText"
Text to display when loading
noDataText
string
default:"$vuetify.noDataText"
Text to display when there are no items
Hides the no data message
Hides the default pagination footer
Hides the default table body
Makes the header fixed while scrolling
Sets the height of the table (enables scrolling)
Adds hover effect on table rows
Adjusts row height. Options: default, comfortable, compact
Emitted when selected items change
Emitted when page changes
Emitted when items per page changes
Emitted when sort configuration changes
Emitted when grouping changes
update:expanded
(expanded: any[]) => void
Emitted when expanded items change
Slot for content above the table
Slot for customizing individual column cells. Replace {key} with the column key
Slot for customizing individual header cells
Slot for content shown when a row is expanded
Slot for custom no data message
Slot for custom loading indicator
Slot for content below the table (replaces default footer)
Examples
Basic Table
<template>
<v-data-table
:headers="headers"
:items="users"
:items-per-page="5"
/>
</template>
<script setup>
const headers = [
{ title: 'Name', key: 'name', align: 'start' },
{ title: 'Email', key: 'email' },
{ title: 'Role', key: 'role' },
{ title: 'Status', key: 'status' },
]
const users = [
{ id: 1, name: 'John Doe', email: '[email protected]', role: 'Admin', status: 'Active' },
{ id: 2, name: 'Jane Smith', email: '[email protected]', role: 'User', status: 'Active' },
{ id: 3, name: 'Bob Johnson', email: '[email protected]', role: 'User', status: 'Inactive' },
]
</script>
Sortable Table
<template>
<v-data-table
:headers="headers"
:items="products"
:sort-by="[{ key: 'price', order: 'desc' }]"
multi-sort
/>
</template>
<script setup>
const headers = [
{ title: 'Product', key: 'name', sortable: true },
{ title: 'Price', key: 'price', sortable: true },
{ title: 'Stock', key: 'stock', sortable: true },
{ title: 'Category', key: 'category', sortable: false },
]
const products = [
{ name: 'Laptop', price: 999, stock: 15, category: 'Electronics' },
{ name: 'Mouse', price: 25, stock: 100, category: 'Accessories' },
{ name: 'Keyboard', price: 75, stock: 50, category: 'Accessories' },
]
</script>
Selectable Rows
<template>
<div>
<v-data-table
v-model="selected"
:headers="headers"
:items="items"
show-select
item-value="id"
/>
<div class="mt-4">
Selected: {{ selected.length }} items
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selected = ref([])
const headers = [
{ title: 'Name', key: 'name' },
{ title: 'Email', key: 'email' },
]
const items = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' },
{ id: 3, name: 'Charlie', email: '[email protected]' },
]
</script>
Custom Cell Slots
<template>
<v-data-table
:headers="headers"
:items="users"
>
<template v-slot:item.status="{ item }">
<v-chip
:color="item.status === 'Active' ? 'success' : 'error'"
size="small"
>
{{ item.status }}
</v-chip>
</template>
<template v-slot:item.actions="{ item }">
<v-btn
icon="mdi-pencil"
size="small"
variant="text"
@click="editItem(item)"
/>
<v-btn
icon="mdi-delete"
size="small"
variant="text"
@click="deleteItem(item)"
/>
</template>
</v-data-table>
</template>
<script setup>
const headers = [
{ title: 'Name', key: 'name' },
{ title: 'Status', key: 'status' },
{ title: 'Actions', key: 'actions', sortable: false },
]
const users = [
{ id: 1, name: 'John Doe', status: 'Active' },
{ id: 2, name: 'Jane Smith', status: 'Inactive' },
]
function editItem(item) {
console.log('Edit', item)
}
function deleteItem(item) {
console.log('Delete', item)
}
</script>
Expandable Rows
<template>
<v-data-table
:headers="headers"
:items="orders"
show-expand
>
<template v-slot:expanded-row="{ item }">
<tr>
<td :colspan="headers.length + 1">
<div class="pa-4">
<strong>Order Details:</strong>
<p>Customer: {{ item.customer }}</p>
<p>Address: {{ item.address }}</p>
<p>Notes: {{ item.notes }}</p>
</div>
</td>
</tr>
</template>
</v-data-table>
</template>
<script setup>
const headers = [
{ title: 'Order ID', key: 'id' },
{ title: 'Date', key: 'date' },
{ title: 'Total', key: 'total' },
]
const orders = [
{
id: '1001',
date: '2024-01-15',
total: '$150.00',
customer: 'John Doe',
address: '123 Main St',
notes: 'Deliver after 5 PM'
},
{
id: '1002',
date: '2024-01-16',
total: '$89.99',
customer: 'Jane Smith',
address: '456 Oak Ave',
notes: 'Ring doorbell'
},
]
</script>
Grouped Table
<template>
<v-data-table
:headers="headers"
:items="employees"
:group-by="[{ key: 'department', order: 'asc' }]"
/>
</template>
<script setup>
const headers = [
{ title: 'Name', key: 'name' },
{ title: 'Position', key: 'position' },
{ title: 'Department', key: 'department' },
]
const employees = [
{ name: 'Alice Johnson', position: 'Developer', department: 'Engineering' },
{ name: 'Bob Smith', position: 'Designer', department: 'Design' },
{ name: 'Charlie Brown', position: 'Developer', department: 'Engineering' },
{ name: 'Diana Prince', position: 'Manager', department: 'Design' },
]
</script>