Alfred-Skyblue / vue-draggable-plus

Universal Drag-and-Drop Component Supporting both Vue 3 and Vue 2
https://vue-draggable-plus.pages.dev/en/
MIT License
3.16k stars 133 forks source link

Using with dynamic sized array #180

Open Cruxial0 opened 2 months ago

Cruxial0 commented 2 months ago

Hi, I am in the process of creating a program that needs to procedurally generate draggable lines.

I am using a similar approach to what's discussed in #1, but dragging onto other lines don't do anything, and reordering elements within the same line results in an error: image

Here is a simplified version of my application:

<div style="margin-top: 10px;">
    <div v-for="(item, i) in lineCollection" :key="`line_${i}`" v-draggable="item" group="lines" class="merge-editor-line" :disabled="disabled" :animation="150" ghostClass="ghost" @onUpdate="onUpdate">
        <MergePatternItem v-for="it in item" :key="it.order" :name="it.name" :kind="it.kind"/>
    </div>
</div>

<script lang="ts">
import { ref } from 'vue'
import{ vDraggable} from 'vue-draggable-plus'
import MergePatternItem from './MergePatternItem.vue'

const lineCollection = ref();
const inputDev = ref('');

let newId = 7277;

export default {
    components: {
        MergePatternItem,
    },
    methods: {
        addItem()
        {
            let inputName = inputDev.value == '' ? 'newItem' : inputDev.value;
            let item = { name: inputName + newId.toString(), kind: '0', id: newId, order: newId };
            lineCollection.value[lineCollection.value.length - 1].push(item);
            newId++;
        },
        setData(data)
        {
            let newData = new Array();
            let order = 0;
            lineCollection.value = [];
            data.forEach(element =>
            {
                let elem = { name: element.name, kind: element.kind, id: element.id, order: order };
                newData.push(elem);
                lineCollection.value[order] = [elem];
                order++;
            });

            newId = order;
        }
    }
}
</script>
Alfred-Skyblue commented 2 months ago

It is recommended to use components or composition functions instead of directives for dynamic lists.

Cruxial0 commented 2 months ago

Using the component approach has an issue with nesting. When I try to set the target variable, I get another error:

image

I assume this is because it looks for the selector of my items before any are generated. Data gets passed into my component using a command after creation. I can't find a way to circumvent this issue without using static data. Any ideas?

<VueDraggable v-model="lineCollection" group="lines" :animation="150" ghostClass="ghost" @onUpdate="onUpdate" target=".merge-item-container">
    <div id="lines" class="merge-editor-line" v-for="line in lineCollection">
        <MergePatternItem v-for="item in line" :key="item.id" :name="item.name" :kind="item.kind"/>
    </div>
</VueDraggable>

In the code above, the .merge-item-container selector is used for the root container in MergePatternItem