Vuetify: Drag and Drop Reordering in Datatables

Created on 18 Oct 2017  路  17Comments  路  Source: vuetifyjs/vuetify

I need the capability to drag and drop the order of items within a Datatable. Is there any way to do this in the current version of Vuetify?

Steps to reproduce

Versions

What is expected ?

What is actually happening ?

Reproduction Link

feature wontfix

Most helpful comment

I use Sortable to implement drag & drop reordering in v-data-table (and others)
(The Vue wrappers you'll find for Sortable won't work with v-data-table)

Example:
https://codepen.io/webifi/pen/qPgbRK?editors=1011
(Updated codepen example to remove sorting from columns)
(Note: This example won't work if you allow vDataTable to sort rows, use pagination, search filtering, etc. Has to just be a simple table that follows the order of items as stored in an array. The order of items in the array will change as you drag and drop to reorder.)

All 17 comments

I use Sortable to implement drag & drop reordering in v-data-table (and others)
(The Vue wrappers you'll find for Sortable won't work with v-data-table)

Example:
https://codepen.io/webifi/pen/qPgbRK?editors=1011
(Updated codepen example to remove sorting from columns)
(Note: This example won't work if you allow vDataTable to sort rows, use pagination, search filtering, etc. Has to just be a simple table that follows the order of items as stored in an array. The order of items in the array will change as you drag and drop to reorder.)

A few things on this. The issue board is reserved for bugs and feature requests. If this is the latter, we would much rather provide a documentation example with this implementation as opposed to add this type of functionality.

@Webifi I love your example and think we should at the very least consider including it in the documentation.

@Webifi Thank you very much! That is perfect.
@johnleider This would definitely be a great addition to the datatables, and lists in v1.0. Especially if you can make sure it works with touch.

@johnleider Thanks. Feel free to use my example.
@mwells3456 I've updated the example to use a WeakMap to obtain a key for each row instead of depending on a unique value in the item. This makes the example implementation a bit more flexible.

I would like to dragging the table elements with solution which Webifi has posted. All Fine and works!
But i need to use a nested table. Iam using the expand slot for recursive table. It works to. But the problem is if i would use both i have a problem with the expand slot becouse this slot is not nested like rendered. It is not under the 'tr' element. The expand Slot is a sibling from 'tr' element. Is it possible to change this? @johnleider

@Floo0S
Best to show an example of what you're trying to do in a codepen.

@Webifi
I have modified your Codepan and adding the Vuetify expand functionality to the table.

https://codepen.io/FlooOS/pen/ZregVL

I commented the "dragReorder" method out to see the problem better.
I think that problem is becouse the expand slot is only a siebling from the element. Would the expand slot be child element from the element all would be fine. And in my opinion, it would be more logical.

Because vDataTable is a tabular structure, I'm not sure the expanded slot could easily be handled the way you'd like in Vuetify.

Gets a little more complicated, but something like this may work in this case:
https://codepen.io/webifi/pen/ddWbvr

In addition to the other changes needed to detect dropping an item between another item and its expand slot, note the :key added to the expand slot content. It's also needed.

(It would be better if the key could be in the expand item's , but there doesn't seem to be a way to do that without modifying Vuetify. I'd have to experiment to see if that fixes some of the rendering issues, but I think it would.)

Created a directive based on this:

import Sortable from "sortablejs"
let sortable;
const SortableTable = {
    bind(el, binding, vnode) {
        let sortableElement = el.getElementsByTagName("tbody")[0];
        const options = {
            handle: ".sortHandle",
            animation: 150,
            onUpdate: function (event) {
                vnode.child.$emit("sorted", event);
            }
        };

        sortable = Sortable.create(sortableElement, options)
    },
};

export default SortableTable;

This emits the Sortablejs event on update. You can add it like this (make sure to import the directive in your component first):

<v-data-table :items="codes"
                      hide-actions
                      hide-headers
                      class="elevation-1 ml-5"
                      no-data-text="No codes found"
                      v-sortable-table
                      @sorted="saveOrder"
        >

In the saveOrder function you can sort the items in the array:

const movedItem = _this.codes.splice(event.oldIndex, 1)[0];
_this.codes.splice(event.newIndex, 0, movedItem);

Adding to @CarlKlein's update, you still need a unique key for the tr elements inside the data-table. Otherwise sorting won't work.

With some slight tweaks, @CarlKlein's solution using the directive works with v-lists as well (codepen). Definitely seems to be the cleanest way to go about this.

Would someone be able to create a codepen V-datatable example using the latest versions of Vuetify (v2.1.10) and Sortablejs (v1.10.1) as I've tried to follow the above using the directive method, but the draggable row functionality doesn't work. Could it be that something in the newest version of Vuetify or Sortablejs has broken dragging? I could do with a working example to check my code against.

@CarlKlein @Webifi have either of you figure out a way to reorder columns?

@mike-seekwell

@CarlKlein @Webifi have either of you figure out a way to reorder columns?

No, sorry, haven't looked into this yet. We will not be upgrading to Vuetify 2 in the coming months so it might take a while.

@mike-seekwell No, haven't had a need to change the order that columns display via drag/drop yet.

Probably wouldn't be too difficult. Use the header slot to generate headers that you can grab, then update the dragReorder method to modify the headers array instead of the data.

Would someone be able to create a codepen V-datatable example using the latest versions of Vuetify (v2.1.10) and Sortablejs (v1.10.1) as I've tried to follow the above using the directive method, but the draggable row functionality doesn't work. Could it be that something in the newest version of Vuetify or Sortablejs has broken dragging? I could do with a working example to check my code against.

@kaitain2019 I was looking for the same thing. I was able to get it to work using this directive:

directives: {
    sortableList: {
      bind (el, binding, vnode) {
        const options = {
          handle: '.sortHandle',
          animation: 150,
          onUpdate: function (event) {
            vnode.child.$emit('sorted', event)
          }
        }
        Sortable.create(el.getElementsByTagName('tbody')[0], options)
      }
    }
  },

note the only thing I've changed is this line:

Sortable.create(el.getElementsByTagName('tbody')[0], options)

I just had to get a sortable data table working for a client. Here's the CodePen I got working: https://codepen.io/NathanWailes/pen/rNLajYO

It uses:
Vue 2.x
Vuetify 2.3.13
Sortable 1.10.2

Was this page helpful?
0 / 5 - 0 ratings