Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Vuetify Data-table: Why Are All Rows Expanding?

Troubleshooting Vuetify data-tables expanding all rows instead of one. Learn how to enable single row expansion without the dropdown icon.
Frustrated developer with Vuetify data-table showing all rows expanded, highlighting issue and single row fix Frustrated developer with Vuetify data-table showing all rows expanded, highlighting issue and single row fix
  • 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.sync lets you control exactly which rows are open.
  • The item-value setting 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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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 expanded array that Vuetify manages
  • The item-value setting 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 expanded array 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.id for item-value
  • Keep the expanded array 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 its item.id.
  • Nothing opens: This might mean item-value is missing or you linked it to data that does not react.
  • A row that was open does not close: You are not resetting the expanded array when you toggle a new row.
  • The wrong row opens: The item.id does not match what is sent to toggleRow(item).

Tools to Help:

  • Use Vue Devtools to look at the array values.
  • Check that the item-value setting matches your toggleRow code.
  • 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 expanded array 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-value is 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


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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading