- Setting
:expanded="true"in Vuetify’s data table makes all rows open by default. - To open rows yourself, you need to copy how Vuetify’s
toggleExpand()works. This gives you control. - Vue's reactivity means you must handle expanded arrays with unique IDs and array methods.
- Using
expanded.synclets you control exactly which rows are open. - The
item-valuesetting makes sure each item has an identity. This is needed to map expanded states correctly.
Understanding Why All Rows Open in Vuetify's Data Table
Here's why all rows open in Vuetify data tables. The Vuetify data table (v-data-table) uses Vue.js. It has sorting, pagination, filtering, and rows you can open up. But when you change how rows work, like hiding the expand icon or using your own buttons, you might see a problem: opening one row opens all of them.
To fix this and get exact control over which rows open, you need to know how Vuetify handles expansion inside and how to make that work with your custom UI.
How a Vuetify Data Table Works With Openable Rows
Vuetify's v-data-table has a way to make rows open built-in using the show-expand setting. This puts an expand icon on the right side of each row. When you click it, it manages the open content using something inside Vuetify: a JavaScript array called expanded. This array holds the IDs of items that are open.
Here is how Vuetify works inside:
<v-data-table
:items="items"
show-expand
item-value="id"
></v-data-table>
It uses:
toggleExpand(item)to change a row’s open state- An
expandedarray that Vuetify manages - The
item-valuesetting used to tell each row apart
This component works well without needing your own code.
And then the whole system reacts to changes. Clicking the default expand icon runs Vuetify’s internal toggleExpand(item) method. This adds or takes away item.id from the expanded array. This, in turn, makes Vue's reactivity system update the correct open parts on the page.
Why Taking Away show-expand Breaks Things
Taking away show-expand stops Vuetify’s built-in open/close parts from working. Sometimes, for design or user experience, people don't want the little arrow. They want to click the whole row or use a custom button.
But without the default expand icon:
- Vuetify no longer knows when to run
toggleExpand() - The
expandedarray inside is not managed - You lose the auto-binding that tells Vuetify which rows are open
What often happens next is people write code that does this:
<tr @click="expanded = true">
<!-- Custom Row UI -->
</tr>
This makes expanded simply true. It doesn't track which row you clicked using an ID. Because of this, all rows open up together. This is wrong.
This is like saying "open everything" because the expanded setting needs an array of the rows you want to open, not just a single true/false value.
How the :expanded Prop Should Work
The :expanded prop in the Vuetify data table is for controlling specific rows. It should always connect to an array. This array needs to hold the IDs that match the item-value prop. This is often a unique ID for each item.
❌ Wrong:
<v-data-table
:items="items"
:expanded="true" <!-- opens all rows without checking which -->
>
</v-data-table>
✅ Right:
<v-data-table
:items="items"
:expanded.sync="expanded"
item-value="id"
>
</v-data-table>
In this right example, Vue's reactivity watches changes to expanded. And then Vuetify uses it to figure out which specific rows are open.
How to Open Just One Row Yourself (The Right Way)
To open only one row at a time and control it yourself, you need a toggle function that targets the right row and the :expanded.sync setting.
Template Example
<template>
<v-data-table
:items="items"
:expanded.sync="expanded"
item-value="id"
>
<template #top>
<h3>Users Table</h3>
</template>
<template v-slot:expanded-item="{ item }">
<div class="my-4 mx-2">
More details for <strong>{{ item.name }}</strong>
</div>
</template>
<template v-slot:item="{ item }">
<tr @click="toggleRow(item)">
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
</tr>
</template>
</v-data-table>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
],
expanded: [],
};
},
methods: {
toggleRow(item) {
this.expanded = this.expanded[0] === item.id ? [] : [item.id];
},
},
};
</script>
This way gives you full control while keeping things the way Vuetify works. The main points are:
- Give each item a unique ID using
item-value - Make the open/close logic work for just one item at a time
- Use a method to toggle instead of just setting true or false
Making State Management Better with Vue.js
Vue's reactivity system works well with arrays that change using methods. Try not to just replace the whole array directly unless you use .sync. Here is a better way:
// Bad
this.expanded = true;
// Good — properly updates the reactive array
Vue.set(this, 'expanded', [item.id]);
// or
this.expanded = [item.id];
Here are some good ways to work:
- Always use a steady and unique
item.idforitem-value - Keep the
expandedarray changing only in ways Vue supports - Use methods that run at the right time to reset the expanded state when data changes
Adding Things to Improve How it Looks and Feels
Visual hints help people see the open data better. You could add animation to the open content or highlight the selected row.
.expanded-row {
transition: background-color 0.3s ease;
background-color: #fcfcfc;
}
Apply it when needed:
<tr :class="{ 'expanded-row': expanded.includes(item.id) }">
Or make the content appear with movement:
.expanded-content {
overflow: hidden;
transition: max-height 0.4s ease;
max-height: 300px;
}
Checking When Expansion Doesn't Work Right
Here are signs and tips if the row expansion does not work right:
Common Issues:
- All rows open: This usually happens because you set
:expanded="true"or did not target a specific row with itsitem.id. - Nothing opens: This might mean
item-valueis missing or you linked it to data that does not react. - A row that was open does not close: You are not resetting the
expandedarray when you toggle a new row. - The wrong row opens: The
item.iddoes not match what is sent totoggleRow(item).
Tools to Help:
- Use Vue Devtools to look at the array values.
- Check that the
item-valuesetting matches yourtoggleRowcode. - Put logs in your
toggleRow(item)function to see every change.
Allowing Two Or More Rows to Be Open at Once
If you want to allow many rows to be open at once, change your toggle logic like this:
methods: {
toggleRow(item) {
const index = this.expanded.indexOf(item.id);
if (index > -1) {
this.expanded.splice(index, 1); // Close this row
} else {
this.expanded.push(item.id); // Open this row
}
}
}
This works more like checkboxes. You can open or close rows freely. It doesn't affect other rows.
Good Ways to Build Components
When your tables get more complex, think about putting the row toggle logic into smaller parts:
<VExpandableRow
:item="item"
:expanded="expanded.includes(item.id)"
@toggle="toggleRow(item)"
/>
This helps you reuse code. It is helpful when you mix open rows with data loading later, rows inside rows, or pop-up windows.
Final Thoughts: How to Get Good at Open Rows in Vuetify Data Tables
To understand open rows in the Vuetify data table, you need to know how Vuetify tracks things inside and how Vue's data system works with that. You will do well whether you use the default icon or a custom clickable row if:
- You link the
expandedarray to the real row IDs. - You keep it reactive using array updates that Vue supports.
- You copy how Vuetify’s
toggleExpand()works exactly. - You know why
item-valueis needed to target rows.
By following these main points, your Vue.js data table will work well. It will provide a good experience for users, whether it has one row open, many, or none to start.
More Things to Read and Watch
- 📖 Vuetify Official Docs: Expandable Rows
- 📺 Vue Tips Video: How to Use Expanded Rows
- 🔧 Best Vue Devtools Debugging Practices
- 📘 Vue Mastery: Understanding Reactivity in Large Components
Citations
Vue.js. (n.d.). Reactivity in depth. Retrieved from https://vuejs.org/guide/essentials/reactivity-fundamentals.html
Vuetify. (n.d.). Data tables — Expandable rows. Retrieved from https://vuetifyjs.com/en/components/data-tables/#expandable-rows
GitHub – Vuetify Issues. (2023). Issue #10123 – All rows expanding if icon is removed.