vue-draggable-plus icon indicating copy to clipboard operation
vue-draggable-plus copied to clipboard

[Feature request] - Add static items inside vDraggable component

Open jakubmatisak opened this issue 1 year ago • 1 comments

Hello, Im dealing with kinda tricky problem. I want to use <table> and make <tr> in thead draggable, but i must have first and last columns fixed. I can disable dragging on first/last item, but all other draggable items can be moved there because <tr> is still draggable. I did not find solution to deal with this in documentation.

I have also found solution in VueDraggableNext https://github.com/SortableJS/vue.draggable.next with header and footer slot (and tried it, it works). It would be lovely to have it there, because I found your solution to be better and more up to date.

This is example how I guess it should be working: In static regions draggable options should be completely deactivated, even if it is inside .

  <draggable
    v-model="list"
    handle=".column__content__handle"
    tag="tr"
    @end="onEnd"
  >
    <!--region static-->
    <td class="staticBefore"></td>
    <!--end region static-->

    <!--region draggable-->
      <td v-for="item in list" :key="item.id" :class="item.name" class="item">
        {{ item.name }}
      </td>
    <!--end region draggable-->

    <!--region static-->
    <td class="staticAfter"></td>
    <!--end region static-->
  </draggable>

Here is also example of application: All is in one <tr> but first two columns has to be there, no matter what..

jakubmatisak avatar Jun 18 '24 07:06 jakubmatisak

Use the target property to select the container with draggable items.

  <draggable
    v-model="list"
    handle=".column__content__handle"
    tag="tr"
    @end="onEnd"
    target=".draggable"
  >
    <td class="staticBefore"></td>

    <!--region draggable-->
      <section class="draggable">
        <td v-for="item in list" :key="item.id" :class="item.name" class="item">
          {{ item.name }}
        </td>
      </section>
    <!--end region draggable-->

    <td class="staticAfter"></td>
  </draggable>

https://vue-draggable-plus.pages.dev/en/demo/target-container/

Mihailoff avatar Jul 14 '24 00:07 Mihailoff

I didn't have time to test this until today because our team has been busy, and our previous solution using draggable-next was working reasonably well. However, we now want to improve it.

An additional issue (which I hadn't mentioned before) is that we're using Vuetify 3's VDataTable, which renders its own internal table structure and classes. Injecting a <section> (or any wrapper element) into the markup breaks Vuetify's behavior — especially within <tr> elements.

Thanks to the hint from @Mihailoff, I found a working solution using display: contents. This allows us to preserve a logical wrapper (.draggable class) without introducing any actual DOM node that would interfere with Vuetify.

<vue-draggable
  v-model="list"
  handle=".column__content__handle"
  tag="tr"
  target=".draggable"
  @end="onEnd"
>
  <th class="staticBefore"></th>

  <!-- Draggable content region (no actual wrapper rendered) -->
  <section
    class="draggable"
    style="display: contents"
  >
    <th
      v-for="item in list"
      :key="item.id"
      :class="item.name"
      class="item"
    >
      {{ item.name }}
    </th>
  </section>

  <th class="staticAfter"></th>
</vue-draggable>

jakubmatisak avatar Jul 30 '25 08:07 jakubmatisak