vuetify icon indicating copy to clipboard operation
vuetify copied to clipboard

[Feature Request] VDataTable should provide a possibility to control groups open/close from outside

Open ChristianRiedl opened this issue 2 years ago • 4 comments

Problem to solve

I tried to convert a grouped List to a DataTable which also supports grouping. But it is not possible to access the opened group list.

Proposed solution

Similar like in List providing v-model:open

ChristianRiedl avatar Aug 04 '23 17:08 ChristianRiedl

~I believe that is what the expanded prop is for, but so far I can't get it working.~

hackel avatar Aug 08 '23 18:08 hackel

@hackel I think expanded state is not related with grouping. It is used to display an additional row of information.

ChristianRiedl avatar Aug 08 '23 20:08 ChristianRiedl

I agree. I want to auto-expand the groups by default (which Vuetify 2 did). Related to #17707. Take this example data:

const items = [
  { id:  1, name: 'Alice', age:  30, group: 'Group A' },
  { id:  2, name: 'Bob', age:  25, group: 'Group B' },
  // More items...
];

And the example table:

<v-data-table
  :items="items"
  :group-by="[{ key: 'group' }]"
> ... </v-data-table>

If I want to expand all the groups, I have no way of doing this. The group-header slot (and others) expose a toggleGroup function. This is exactly what we want, just available outside of the template, for example in the mounted hook.

luc122c avatar Feb 27 '24 15:02 luc122c

I stumbled upon this problem today...

Inspired by Chris' answer and the Group header slot example, I came up with the code below:

We initially save the properties we need in the groupHeaders object.

Then we replicate the current group header functionality of Vuetify.

<template #group-header="{ item, columns, toggleGroup, isGroupOpen }">
    <template :ref="(el) => { this.groupHeaders[item.value] = { item, toggleGroup, isGroupOpen } }" />
    <tr>
        <td :colspan="columns.length">
            <v-btn
                :icon="isGroupOpen(item) ? '$expand' : '$next'"
                size="small"
                variant="text"
                @click="toggleGroup(item)"
            />
            {{ item.value }} ({{ item.items.length }})
        </td>
    </tr>
</template>

Now we can toggle one or more groups when we need them (e.g. onMounted):

Either on a specific group header by filtering OUR_VALUE:

const headerToToggle = this.groupHeaders[OUR_VALUE]
headerToToggle?.toggleGroup(headerToToggle.item)

Or on all group headers massively:

Object.values(this.groupHeaders).forEach((header) => {
    header.toggleGroup(header.item))
})

EDIT: A bit of refactoring for better results.

crazyrabbit0 avatar Apr 25 '24 20:04 crazyrabbit0

@crazyrabbit0

this only works on visible rows. I have a table with multiple nested groups and the ones off-screen (nested or root) are ignored. I tried both v-data-table-virtual and v-data-table with :items-per-page="-1"

philly-vanilly avatar Jul 24 '24 03:07 philly-vanilly

Interesting, can you share your code to check what went wrong ?

crazyrabbit0 avatar Jul 24 '24 07:07 crazyrabbit0