How can I drag element into another one with vue-draggable

33 views Asked by At

I have nested elements that need to be draggable in between. My problem is at the same level there are elements and when I drag one into another one I want them to have a parent-child relationship but thats not possible. My application was developed with Vue 2. For this, I have ElementsList component (I cleaned the fetching data part because my problem is draggable). So here is ElementsList component:

<template>
    <draggable
        v-model="newElement"
        v-bind="dragOptions"
    >
        <transition-group>
            <NestedElement
                v-for="(element, index) in newElement"
                :key="`${element.id}_${index}`"
                :element="element"
                :is-expanded="isExpanded"
                :users="users"
            />
        </transition-group>
    </draggable>
</template>

<script>

export default {
    components: {
        NestedElement,
        draggable,
    },
    props: {
        elements: {
            type: Array,
            required: true,
            default: () => [],
        },
        isExpanded: {
            type: Boolean,
            required: false,
            default: false,
        },
        users: {
            required: false,
            type: Array,
            default: () => [],
        },
    },
    data() {
        return {
            newElement: [],
            dragOptions: {
                group: "plan-elements",
                animation: 150,
                ghostClass: "ghost",
                forceFallback: true,
                fallbackOnBody: true,
                chosenClass: "dragging",
                pull: "clone",
            },
        };
    },
    watch: {
        elements: {
            async handler() {
                if (elements.length) {
                    this.isLoading = false;
                    this.newElement = elements;
                }
            },
            immediate: true,
        },
    },
};
</script>

and this is NestedElement component:

<template>
    <div>
        <Element
            :element="element"
            @toggle-accordion="toggleAccordion"
            :has-child="hasChildElement"
            :is-expanded="isAllOpen"
            :users="users"
        />
        <draggable
            v-if="(isOpen || (isOpen && isAllOpen)) && element.childElements && element.childElements.data"
            v-model="element.childElements.data"
            v-bind="dragOptions"
            class="child-elements-container"
        >
            <transition-group>
                <NestedElement
                    v-for="(childElement, index) in element.childElements.data"
                    :key="`${childElement.id}_${index}`"
                    :element="childElement"
                    :is-open="isOpen"
                    :is-expanded="isAllOpen"
                />
            </transition-group>
        </draggable>
    </div>
</template>

<script>

export default {
    name: "NestedElement",
    components: {
        Element,
        draggable,
    },
    props: {
        element: {
            required: true,
        },
        isExpanded: {
            type: Boolean,
            required: false,
            default: false,
        },
        draggableEvent: {
            type: Object,
            required: false,
        },
        users: {
            required: false,
            type: Array,
            default: () => [],
        },
    },
    data() {
        return {
            dragOptions: {
                group: "plan-elements",
                animation: 150,
                ghostClass: "ghost",
                forceFallback: true,
                fallbackOnBody: true,
                chosenClass: "dragging",
                pull: "clone",
            },
            isAllOpen: false,
            isOpen: false,
        };
    },
    computed: {
        hasChildElement() {
            if (this.element.childElements) {
                return this.element.childElements.data.length ? true : false;
            }
        },
    },
    methods: {
        toggleAccordion(isOpen) {
            this.isOpen = isOpen;
        },
    },
    watch: {
        isExpanded: {
            handler(newVal) {
                this.isAllOpen = newVal;
                this.isOpen = newVal;
            },
            immediate: true,
        },
    },
};
</script>

Element component is the one that I work for displaying so I dont think it has a role in this question. Currently, if the element has a child element, I can drag another element into that one and have a parent-child relationship. But when there is no child, I cannot drag into another.

Thanks for the help in advance.

0

There are 0 answers