Data tables
The v-data-table component is used for displaying tabular data. Features include sorting, searching, pagination, grouping, and row selection.
Usage
The standard data table presumes that the entire data set is available locally. Sorting, pagination, and filtering is supported and done internally by the component itself.
<v-data-table :items="items"></v-data-table><script setup>
const items = [
{
name: 'African Elephant',
species: 'Loxodonta africana',
diet: 'Herbivore',
habitat: 'Savanna, Forests',
},
// ... more items
]
</script>API
| Component | Description |
|---|---|
| v-data-table | Primary Component |
| v-data-table-headers | Functional Component used to display Data-table headers |
| v-data-table-footer | Functional Component used to display Data-table footers |
| v-data-table-row | Functional Component used to display a single row of a data-table |
| v-data-table-rows | Functional Component used to display all of the rows in a data-table |
| v-checkbox-btn | Reusable lightweight v-checkbox |
Server side tables
This variant of the data table is meant to be used for very large datasets, where it would be inefficient to load all the data into the client. It supports sorting, filtering, pagination, and selection like a standard data table, but all the logic must be handled externally by your backend or database.
| Component | Description |
|---|---|
| v-data-table-server | Primary Component |
Find more information and examples on the Server side tables page.
Car Model | Horsepower | Fuel Type | Origin | Price ($) |
|---|---|---|---|---|
| Ford Mustang | 450 | Gasoline | USA | 55000 |
| Tesla Model S | 670 | Electric | USA | 79999 |
| BMW M3 | 503 | Gasoline | Germany | 70000 |
| Audi RS6 | 591 | Gasoline | Germany | 109000 |
| Chevrolet Camaro | 650 | Gasoline | USA | 62000 |
Virtual tables
The virtual variant of the data table relies, like the standard variant, on all data being available locally. But unlike the standard variant it uses virtualization to only render a small portion of the rows. This makes it well suited for displaying large data sets. It supports client-side sorting and filtering, but not pagination.
| Component | Description |
|---|---|
| v-data-table-virtual | Primary Component |
Find more information and examples on the Virtual tables page.
Boat Type | Speed(knots) | Length(m) | Price($) | Year |
|---|---|---|---|---|
| Speedster #0 | 35 | 22 | $300,000 | 2021 |
| OceanMaster #1 | 25 | 35 | $500,000 | 2020 |
| Voyager #2 | 20 | 45 | $700,000 | 2019 |
| WaveRunner #3 | 40 | 19 | $250,000 | 2022 |
| SeaBreeze #4 | 28 | 31 | $450,000 | 2018 |
| HarborGuard #5 | 18 | 50 | $800,000 | 2017 |
| SlickFin #6 | 33 | 24 | $350,000 | 2021 |
| StormBreaker #7 | 22 | 38 | $600,000 | 2020 |
| WindSail #8 | 15 | 55 | $900,000 | 2019 |
| FastTide #9 | 37 | 20 | $280,000 | 2022 |
| Speedster #10 | 35 | 22 | $300,000 | 2021 |
| OceanMaster #11 | 25 | 35 | $500,000 | 2020 |
| Voyager #12 | 20 | 45 | $700,000 | 2019 |
| WaveRunner #13 | 40 | 19 | $250,000 | 2022 |
| SeaBreeze #14 | 28 | 31 | $450,000 | 2018 |
| HarborGuard #15 | 18 | 50 | $800,000 | 2017 |
| SlickFin #16 | 33 | 24 | $350,000 | 2021 |
| StormBreaker #17 | 22 | 38 | $600,000 | 2020 |
| WindSail #18 | 15 | 55 | $900,000 | 2019 |
| FastTide #19 | 37 | 20 | $280,000 | 2022 |
| Speedster #20 | 35 | 22 | $300,000 | 2021 |
| OceanMaster #21 | 25 | 35 | $500,000 | 2020 |
| Voyager #22 | 20 | 45 | $700,000 | 2019 |
| WaveRunner #23 | 40 | 19 | $250,000 | 2022 |
| SeaBreeze #24 | 28 | 31 | $450,000 | 2018 |
Guide
The v-data-table component is a simple and powerful table manipulation component. It is perfect for showing large amounts of tabular data.
Items
Table items can be objects with almost any shape or number of properties. The only requirement is some form of unique identifier if row selection is being utilized.
Headers
The headers array is the core of the table. It defines which properties to display, their associated labels, how they should be sorted, and what they should look like.
All properties are optional, but at least one of title, value, or key should be present to display more than just an empty column:
const headers = [
{ title: 'No data, just a label' },
{ key: 'quantity' },
{ value: 'price' },
]
Without any headers defined, the table will use all the keys of the first item as headers.
Headers can also be a tree structure with a children property to create multi-row header labels with rowspan and colspan calculated automatically.
Leaf nodes (objects without children) will be used as columns for each item.
Branch nodes (objects with children) support all the same sorting and filtering options as leaf nodes, but cannot be used as columns.
Pyramid | Location | Construction Date | Dimensions | ||
|---|---|---|---|---|---|
Height(m) | Base(m) | Volume(m³) | |||
| Great Pyramid of Giza | Egypt | c. 2580–2560 BC | 146.6 | 230.4 | 2583285 |
| Pyramid of Khafre | Egypt | c. 2570 BC | 136.4 | 215.3 | 1477485 |
| Red Pyramid | Egypt | c. 2590 BC | 104 | 220 | 1602895 |
| Bent Pyramid | Egypt | c. 2600 BC | 101.1 | 188.6 | 1200690 |
| Pyramid of the Sun | Mexico | c. 200 CE | 65 | 225 | 1237097 |
Keys and values
The key property is used to identify the column in slots, events, filters, and sort functions. It will default to the value property if value is a string.
value maps the column to a property in the items array. If value is not defined it will default to key, so key and value are interchangeable in most cases. The exception to this is reserved keys like data-table-select and data-table-expand which must be defined as key to work properly.
key and value both support dot notation to access properties of nested objects, and value can also be a function to combine multiple properties or do other custom formatting. If value is not a string then key must be defined.
const items = [
{
id: 1,
name: {
first: 'John',
last: 'Doe',
},
},
]
const headers = [
{ title: 'First Name', value: 'name.first' },
{ title: 'Last Name', key: 'name.last' },
{
title: 'Full Name',
key: 'fullName',
value: item => `${item.name.first} ${item.name.last}`,
},
]
Sorting, filtering, pagination
See Data and display.
Customization
Other options are available for setting width, align, fixed, or pass custom props to the header element with headerProps and row cells with cellProps.
Props
There is no shortage of properties available for customizing various aspects of the Data table components.
Density
Using the density prop you are able to give your data tables an alternate style.
Plant | Light | Height | Pet Friendly | Price ($) |
|---|---|---|---|---|
| Fern | Low | 20cm | Yes | 20 |
| Snake Plant | Low | 50cm | No | 35 |
| Monstera | Medium | 60cm | No | 50 |
| Pothos | Low to medium | 40cm | Yes | 25 |
| ZZ Plant | Low to medium | 90cm | Yes | 30 |
| Spider Plant | Bright, indirect | 30cm | Yes | 15 |
| Air Plant | Bright, indirect | 15cm | Yes | 10 |
| Peperomia | Bright, indirect | 25cm | Yes | 20 |
| Aloe Vera | Bright, direct | 30cm | Yes | 15 |
| Jade Plant | Bright, direct | 40cm | Yes | 25 |
Sort icons
You can customize sorting icons using dedicated props as well as control default opacity and spacing with Sass variables.
Dessert (100g serving) | Calories | Fat (g) | Carbs (g) | Protein (g) |
|---|---|---|---|---|
| Frozen Yogurt | 159 | 6 | 24 | 4 |
| Ice cream sandwich | 237 | 9 | 37 | 4.3 |
| Eclair | 262 | 16 | 23 | 6 |
| Cupcake | 305 | 3.7 | 67 | 4.3 |
Selection
The show-select prop will render a checkbox in the default header to toggle all rows, and a checkbox for each row.
For more information and examples, see the selection examples page.
Name | Location | Height | Base | Volume | |
|---|---|---|---|---|---|
| 🍎 Apple | Washington | 0.1 | 0.07 | 0.0001 | |
| 🍌 Banana | Ecuador | 0.2 | 0.05 | 0.0002 | |
| 🍇 Grapes | Italy | 0.02 | 0.02 | 0.00001 | |
| 🍉 Watermelon | China | 0.4 | 0.3 | 0.03 | |
| 🍍 Pineapple | Thailand | 0.3 | 0.2 | 0.005 | |
| 🍒 Cherries | Turkey | 0.02 | 0.02 | 0.00001 | |
| 🥭 Mango | India | 0.15 | 0.1 | 0.0005 | |
| 🍓 Strawberry | USA | 0.03 | 0.03 | 0.00002 | |
| 🍑 Peach | China | 0.09 | 0.08 | 0.0004 | |
| 🥝 Kiwi | New Zealand | 0.05 | 0.05 | 0.0001 |
Simple checkbox
When wanting to use a checkbox component inside of a slot template in your data tables, use the v-checkbox-btn component rather than the v-checkbox component.
Name | Manufacturer | Year | Sales | Exclusive |
|---|---|---|---|---|
| PlayStation 5 | Sony | 2020 | 10M | |
| Xbox Series X | Microsoft | 2020 | 6.5M | |
| Nintendo Switch | Nintendo | 2017 | 89M | |
| PlayStation 4 | Sony | 2013 | 116M | |
| Xbox One | Microsoft | 2013 | 50M | |
| Nintendo Wii | Nintendo | 2006 | 101M |
Group by
The group-by prop makes it possible to group rows by one or more attributes.
Category | Dessert (100g serving) | Dairy |
|---|---|---|
| Candy(3) | ||
| Cookie(2) | ||
| Ice cream(2) | ||
| Pastry(2) | ||
| Toffee(1) | ||
Slots
Header slot
You can use the dynamic slots header.<key> to customize only certain columns. <key> corresponds to the key property in the items found in the headers prop.
There are two built-in slots for customizing both the select (header.data-table-select) and expand (header.data-table-expand) columns when using show-select and show-expand props respectively.
| ID | Name | Size | Color | Price | Quantity |
|---|---|---|---|---|---|
| 1 | T-Shirt | M | Red | 19.99 | 10 |
| 2 | Jeans | 32 | Blue | 49.99 | 5 |
| 3 | Sweater | L | Green | 29.99 | 7 |
| 4 | Jacket | XL | Black | 89.99 | 3 |
| 5 | Socks | One Size | White | 9.99 | 20 |
Headers slot
You can also override all the internal headers by using the headers slot. Remember that you will have to re-implement any internal functionality like sorting.
Dessert | Calories | Fat(g) | Carbs(g) | Protein(g) | Iron(%) |
|---|---|---|---|---|---|
| Frozen Yogurt | 159 | 6 | 24 | 4 | 1 |
| Ice cream sandwich | 237 | 9 | 37 | 4.3 | 1 |
| Eclair | 262 | 16 | 23 | 6 | 7 |
| Cupcake | 305 | 3.7 | 67 | 4.3 | 8 |
| Gingerbread | 356 | 16 | 49 | 3.9 | 16 |
Item slot
Normally you would use the item.<key> slots to render custom markup in specific columns. If you instead need more control over the entire row, you can use the item slot.
ID | Name | Dept | Role | Salary($) | HireDate | Hours/Wk | Location | Status | Score |
|---|---|---|---|---|---|---|---|---|---|
| E001 | Alice Johnson | Engineering | Software Dev | $95,000 | 2020-03-15 | 40 | New York | Full-Time | 4.50 |
| E002 | Bob Carter | Sales | Account Manager | $72,000 | 2019-11-01 | 35 | Chicago | Full-Time | 4.20 |
| E003 | Clara Diaz | HR | Recruiter | $65,000 | 2021-06-10 | 32 | Remote | Part-Time | 4.00 |
| E004 | David Lee | Engineering | DevOps Engineer | $105,000 | 2018-09-22 | 40 | San Francisco | Full-Time | 4.70 |
| E005 | Ella Smith | Marketing | Social Media Mgr | $80,000 | 2020-01-05 | 38 | Los Angeles | Full-Time | 4.30 |
Item key slot
You can use the dynamic slots item.<key> to customize only certain columns. <key> is the name of the key property in header items sent to headers. So to customize the calories column we’re using the item.calories slot.
Vegetable | Calories | Fat(g) | Carbs(g) | Protein(g) | Iron(%) |
|---|---|---|---|---|---|
| Spinach | 23 | 0.4 | 3.6 | 2.9 | 15% |
| Kael | 49 | 0.9 | 8.8 | 4.3 | 16% |
| Broccoli | 34 | 0.4 | 6.6 | 2.8 | 6% |
| Brussels Sprouts | 43 | 0.3 | 8.9 | 3.4 | 9% |
| Avocado | 160 | 15 | 9 | 2 | 3% |
| Sweet Potato | 86 | 0.1 | 20.1 | 1.6 | 3% |
| Corn | 96 | 1.5 | 21 | 3.4 | 2% |
| Potato | 77 | 0.1 | 17.5 | 2 | 8% |
| Butternut Squash | 45 | 0.1 | 11.7 | 1 | 4% |
| Beetroot | 43 | 0.2 | 10 | 1.6 | 6% |
Group header slot
When using the group-by prop, you can customize the group header with the group-header slot. Example below makes the whole row clickable.
Group | Tool Name | Weight(kg) | Length(cm) | Price($) |
|---|---|---|---|---|
Tool Type: hand | ||||
Tool Type: measuring | ||||
Tool Type: power | ||||
Group summary slot
By default grouping with group-by shows only the header slot. When you define group-summary slot, additional summary row will appear below the group rows.
Group | Tool Name | Weight(kg) | Length(cm) | Price($) |
|---|---|---|---|---|
| hand(5) | ||||
| measuring(3) | ||||
| power(2) | ||||
Loading slot
The loading slot allows you to customize your table’s display state when fetching data. In this example we utilize the v-skeleton-loader component to display a loading animation.
Name | Year | Engine | Horsepower | Torque |
|---|---|---|---|---|
| Chevrolet Camaro | 1967 | V8 | 375 | 415 |
| Ford Mustang | 1965 | V8 | 271 | 312 |
| Dodge Charger | 1968 | V8 | 425 | 490 |
| Pontiac GTO | 1964 | V8 | 350 | 445 |
| Plymouth Barracuda | 1964 | V8 | 330 | 425 |
| Chevrolet Chevelle SS | 1970 | V8 | 450 | 500 |
| Oldsmobile 442 | 1971 | V8 | 340 | 440 |
| Dodge Challenger | 1970 | V8 | 425 | 490 |
| AMC Javelin | 1968 | V8 | 315 | 425 |
| Mercury Cougar | 1967 | V8 | 335 | 427 |
Misc
Select All
The example below shows how to use the @keydown event to quickly select all rows in the data table using the Ctrl+A or Cmd+A keyboard shortcut. To begin using the shortcut, click anywhere inside the table first.
Name | Email | Age | |
|---|---|---|---|
| Alice Johnson | alice@example.com | 42 | |
| Bob Smith | bob@example.com | 36 | |
| Charlie Davis | charlie@example.com | 24 | |
| Diana Prince | diana@example.com | 30 |
Examples
The following are a collection of examples that demonstrate more advanced and real world use of the v-data-table component.
CRUD Actions
v-data-table with CRUD actions using a v-dialog component for editing each row
Title | Author | Genre | Year | Pages | Actions |
|---|---|---|---|---|---|
To Kill a Mockingbird | Harper Lee | Fiction | 1960 | 281 | |
1984 | George Orwell | Dystopian | 1949 | 328 | |
The Great Gatsby | F. Scott Fitzgerald | Fiction | 1925 | 180 | |
Sapiens | Yuval Noah Harari | Non-Fiction | 2011 | 443 | |
Dune | Frank Herbert | Sci-Fi | 1965 | 412 |
Expandable rows
The show-expand prop will render an expand icon on each row. You can customize this with the item.data-table-expand slot. The position of this slot can be changed by adding a column with key: 'data-table-expand' to the headers array.
You can override the rows expand icon via the item.data-table-expand slot. To call upon the expand functionality, pass the slots provided internalItem to the toggleExpand function and add it to a click handler to perform the expand functionality. You can also check the current state of the rows expansion by passing the internalItem to the isExpanded function.
Just like selection, row items require a unique property on each item for expansion to work. The default is id, but you can use the item-value prop to specify a different item property.
Title | Director | Genre | Year | Runtime(min) | |
|---|---|---|---|---|---|
| The Shawshank Redemption | Frank Darabont | Drama | 1994 | 142 | |
| Inception | Christopher Nolan | Sci-Fi | 2010 | 148 | |
| The Godfather | Francis Ford Coppola | Crime | 1972 | 175 | |
| Pulp Fiction | Quentin Tarantino | Crime | 1994 | 154 | |
| The Dark Knight | Christopher Nolan | Action | 2008 | 152 |