How can I make vue-draggable element with button

95 views Asked by At

I want to have a draggable element with a button for my vue 2 application. For this, I am using vue-draggable. So something like that in the picture: enter image description here

So currently, when I click the button (the one with icon), draggable triggers also. So what I am trying to achieve is when I click the button, draggable should stop and whenever I click outside of the button, draggable should be triggered again. So for this here is my NestedElement component:

<template>
    <div>
        <ClimatePlanElement
            :element="element"
            @toggle-accordion="toggleAccordion"
            :has-child="hasChildElement"
            :is-expanded="isAllOpen"
            :users="users"
            @disable-draggable="disableDrag"
        />
        <draggable
            v-if="isOpen || (isOpen && isAllOpen)"
            v-model="element.childElements.data"
            v-bind="dragOptions"
            class="child-elements-container"
            @start="enableDrag=true" 
            @end="enableDrag=false" 
            :disabled="!enableDrag"
        >
            <transition-group>
                <NestedPlanElement
                    v-for="(childElement, index) in element.childElements.data"
                    :key="`${childElement.id}_${index}`"
                    :element="childElement"
                    :is-open="isOpen"
                    :is-expanded="isAllOpen"
                    @button-clicked="disableDrag"
                />
            </transition-group>
        </draggable>
    </div>
</template>

<script>
export default {
    name: "NestedPlanElement",
    components: {
        draggable,
    },
    props: {
        element: {
            required: true,
        },
        isExpanded: {
            type: Boolean,
            required: false,
            default: 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,
            enableDrag: true,
        };
    },
    computed: {
        hasChildElement() {
            if (this.element.childElements) {
                return this.element.childElements.data.length ? true : false;
            }
        },
    },
    methods: {
        disableDrag() {
            this.enableDrag = false;
        },
        toggleAccordion(isOpen) {
            this.isOpen = isOpen;
        },
    },
    watch: {
        isExpanded: {
            handler(newVal) {
                this.isAllOpen = newVal;
                this.isOpen = newVal;
            },
            immediate: true,
        },
    },
};
</script>

and this is my Element component:

<template>
    <div class="plan-element">
        <div class="plan-element-details">
            <button v-if="hasChild" class="flex-secondary-button acccordion-button" @click="toggleAccordion">
                <i :class="['fa', 'fa-chevron-right', {'rotate-90': isAccordionOpen}]"></i>
            </button>
        </div>
    </div>
</template>
<script>
export default {
    props: {
        hasChild: {
            type: Boolean,
            required: true,
            default: false,
        },
        isExpanded: {
            type: Boolean,
            default: false,
        },
        users: {
            required: false,
            type: Array,
            default: () => [],
        },
    },
    data() {
        return {
            isAccordionOpen: false,
        };
    },
    methods: {
        toggleAccordion() {
            this.isAccordionOpen = !this.isAccordionOpen;
            this.$emit("toggle-accordion", this.isAccordionOpen);
            this.$emit("button-clicked");
        },
    },
    watch: {
        isExpanded: {
            handler(newValue) {
                this.isAccordionOpen = newValue;
            },
            immediate: true,
        },
    },
};
</script>

So currently, this doesnt work at all. How can I create this feature?

0

There are 0 answers