2
votes

I am trying to implement drag and drop on Vuetify Treeview and data table. It seems like it is not supported fully but a workaround is described in this thread. The workaround is however not complete. Perhaps the community would benefit if someone created a codepen or similar on this?

What confuses me is that the component DragDropSlot.vue is created but "drag-drop-slot" is used in the code. Also there is a "_.cloneDeep(this.tree)" call where _ is not defined. I assume it should be replaced by something. When I comment that out drag and drop does still not work. Probably missed something more like defining data. Not sure of correct data types. It seems to be based on react which I have not worked with. Have just started to learn vue and vuetify.

I'm open for any suggestion for how to solve this.

All the best

3

3 Answers

3
votes

I use V-Treeview with Vue.Draggable (https://github.com/SortableJS/Vue.Draggable). I use direct link.

<script src="//cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0 vuedraggable.umd.min.js"/>
<v-treeview
:active.sync="active"
:items="users"
:search="search"
item-key="Id"
item-text="UserName"
item-children="Children"
:open.sync="open"
activatable
color="warning"
dense
transition
return-object
>
<template v-slot:label="{ item }">
<draggable :list="users" group="node" :id="item.Id" :data-parent="item.ParentId" @start="checkStart" @end="checkEnd"    >
    <label>
        <i class="fas fa-user mr-3" />
        <span id="item.id" >{{item.UserName}}</span>
    </label>  
</draggable>

Also I add ParentId property to item tree model: { Id:1, UserName: "John Doe", ParentId: null, Children:[{Id:2, ParentId: 1,...}] }
Then I use start and end events where I search parent start node from I drag the item and parent end node where I drop the item. When parent is null the item is a root.

new Vue({
        el: '#app',
        vuetify: new Vuetify(),
        components: {
            vuedraggable
        },
        data() {
            return {
                active: [],
                open: [],
                users: [],
                selectedItems: [],
            }
        },
        mounted: function () {
            this.fetchUsers();
        },
        methods: {
            findTreeItem: function (items, id) {
                if (!items) {
                    return;
                }
                for (var i = 0; i < items.length; i++) {
                    var item = items[i];
                    // Test current object
                    if (item.Id === id) {
                        return item;
                    }
                    // Test children recursively
                    const child = this.findTreeItem(item.Children, id);
                    if (child) {
                        return child;
                    }
                }
            },
            checkStart: function (evt) {
                var self = this;
                self.active = [];
                self.active.push(self.findTreeItem(self.users, evt.from.id))
            },
            checkEnd: function (evt) {
                var self = this;
                var itemSelected = self.active[0];
                var fromParent = itemSelected.ParentId ? self.findTreeItem(self.users, itemSelected.ParentId) : null;
                var toParent = self.findTreeItem(self.users, evt.to.id);
                var objFrom = fromParent ? fromParent.Children : self.users;
                objFrom.splice(objFrom.indexOf(itemSelected), 1);

                if (toParent.Id === itemSelected.Id) {
                    itemSelected.ParentId = null;
                    self.users.push(itemSelected);
                }
                else {
                    itemSelected.ParentId = toParent.Id;
                    toParent.Children.push(itemSelected);
                }
                self.saveUser(itemSelected);
                //   self.active = [];
                return false;
            },
            fetchUsers: function () {
                //load from api
            },
            saveUser: function (user) {
                //save 
            },

        },
        computed: {
            selected() {
                if (!this.active.length) return undefined
                return this.active[0];
            },
        }
    })

Hope I help you. IngD.

1
votes

After some additional work I ended up with implementing Drag and Drop on top of vuetify tree view and data table using this library:

https://www.vuetoolbox.com/projects/vue-drag-drop

At first I looked at draggable and similar but realized it was always based on that you move an element from position A to position B. I needed more control. For example I wanted the element to disappear when dropping on some drop zones.

0
votes

found this component.

https://vuejsexamples.com/vuetify-draggable-v-treeview-component/

I didn't try it myself (because it has too few options), but it looks working well in demo.

Anyways, just to try