Draggable table row with VueJS, Vuetify and SortableJS

gaisinskii

Andrey Gaisinskii

Posted on June 21, 2020

Draggable table row with VueJS, Vuetify and SortableJS

TLDR At the bottom of the article you will find a link to the GitHub repo.

Prologue

Recently I have had to implement draggable rows for a vuetify table and right off the bat started searching in the docs and the webs for a solution. And came across this article written by Abhay Wawale and some other answers on StackOverflow & CodePen.

The article is great, but I was concerned about manipulating the DOM directly. As for me it is a bit hacky.

My Solution

Instead of accessing the item slot in v-data-table I decided to mess around with the body slot. Basically body slot is your <tbody> html tag and it is very nice since we need a tag prop for vuedraggable component which is a wrapper for SortableJS.



    <v-data-table>
      <template v-slot:body="props">
        <draggable
          :list="props.items"
          tag="tbody"
        >
          <!-- the row will go here -->
        </draggable>
      </template>
    </v-data-table>


Enter fullscreen mode Exit fullscreen mode

Now to the rows, you just have to loop through the array of items that you pass into your v-data-table items prop. Those items will be exposed in the body slot and can be accessed as follows:



          <tr
            v-for="(item, index) in props.items"
            :key="index"
          >
            <td> {{ item.your-property-here }} </td>
          </tr>


Enter fullscreen mode Exit fullscreen mode

Let's add some actual data and make our table more fancy:



    <v-data-table
      :headers="tableHeaders"
      :items="tableItems"
      :loading="loading"
      item-key="id"
      :show-select="false"
      :disable-pagination="true"
      :hide-default-footer="true"
      class="page__table"
    >
      <template v-slot:body="props">
        <draggable
          :list="props.items"
          tag="tbody"
        >
          <tr
            v-for="(user, index) in props.items"
            :key="index"
          >
            <td>
              <v-icon
                small
                class="page__grab-icon"
              >
                mdi-arrow-all
              </v-icon>
            </td>
            <td> {{ index + 1 }} </td>
            <td> {{ user.id }} </td>
            <td> {{ user.name }} </td>
            <td> {{ user.username }} </td>
            <td> {{ user.email }} </td>
            <td> {{ user.website }} </td>
            <td>
              <v-icon
                small
                @click="editUser(user.id)"
              >
                mdi-pencil
              </v-icon>
            </td>
          </tr>
        </draggable>
      </template>
    </v-data-table>


Enter fullscreen mode Exit fullscreen mode

Our table will look like this and draggable rows are working!

Our table!

Thanks for reading!

Code can be found here and live preview here

💖 💪 🙅 🚩
gaisinskii
Andrey Gaisinskii

Posted on June 21, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related