Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using vuedraggable inside vuetify v-data-table two slots breaking the tbody-tr-td structure #1212

Open
wcywin opened this issue Jun 16, 2023 · 2 comments

Comments

@wcywin
Copy link

wcywin commented Jun 16, 2023

Github repo link:

https://github.com/wcywin/nuxt-3-vuetify-3-vuedraggable-v-data-table

Netlify link:

https://cerulean-tanuki-4c3a9e.netlify.app/

Step-by-step scenario

  1. When using Vuetify 3 and its v-data-table
  2. The draggable wrapper has to land inside the tbody slot of v-data-table
  3. the draggable itself has an additional slot of '#item'
  4. The table ends up heaving either 2x tbody or 2x tr and therefore is breaking the table structure of tbody-tr-td
  5. Therefore the UI breaks.

Actual Solution

  1. In Vuedraggable 2, the draggable component did not have a named slot inside, so only one tag in html appeared.
  2. In order to work in vuetify 3, we need to use the v-table component.
  3. Not using v-data-table we are losing its default functionality including headers and pagination.

Expected Solution

  1. The solution would be to allow the Draggable component to be a 'transparent' div, or its item slot to be a 'transparent' template, or to enable the item slot to render multiple children (as it shows an error of only 1 child to be rendered in the slot - but not accepting the template tag).
@fabioselau077
Copy link

fabioselau077 commented Dec 2, 2023

Same issue here... Any solutions?

You have example using v-table?

@RajeevSiewnath
Copy link

Yeah I managed to work around this fairly easy and with quite little effort

The issue is actually the double rendered tbody that comes from the <template #body={ items } /> slot. This was never an issue in Vuetify2 because the body slot allowed you to defined the tbody tag yourself as well. That would look something like this:

<v-data-table :headers="[]" :items="items">
  <template #body="{ items }">
    <draggable :list="[...items]" item-key="id" tag="tbody">
      <template #item="{ element: field }">
        <tr class="v-data-table__tr v-data-table__tr--clickable" @click="onRowClick(field)">
          <td class="v-data-table__td v-data-table-column--align-start">
            {{ item.whateverValue }}
          </td>
        </tr>
      </template>
    </draggable>
  </template>
</v-data-table>

This will render the tbody twice though and will mess up the table structure. But in vue3 when you add the following snippet in an onMounted callback of the component that renders the table it should look good and work all again.

onMounted(() => {
  const sortableTbody = document.querySelector('.v-table__wrapper > table > tbody > tbody')
  const tbody = document.querySelector('.v-table__wrapper > table > tbody')
  tbody!.parentNode!.append(sortableTbody!)
  tbody!.remove()
})

Keep in mind you have to take the whole draggable DOM node otherwise it won't of course work. That's why in the draggable component I have set the tag to tbody to exactly replace the tbody that is automatically placed there by Vuetify.

Small disclaimer: I have only used this in Vue3 not with Nuxt3, there might be some complications with the whole SSR part, but I'm sure you can get around that by executing the onMount part only client side.

Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants