plantain-00 / tree-component

A reactjs and vuejs tree component.
MIT License
146 stars 32 forks source link

Drag & Drop to/from another tree #19

Closed v1r0x closed 5 years ago

v1r0x commented 5 years ago

I'm a huge fan of this component and successfully using it in two of my projects. But for one of the projects I need to move/copy nodes from one tree to another. Would be nice to have this feature in this component :)

plantain-00 commented 5 years ago

v5.6.0 can drag and drop node between different trees by dragTarget and changeDragTarget

v1r0x commented 5 years ago

Thanks for the quick implementation! :tada: I'll have a look at it next week :)

v1r0x commented 5 years ago

I finally had some time for testing. Unfortunately, it didn't work for me, but this might be related to the fact, that I have both trees in their own vue component.

Is this not supported or am I missing something?

plantain-00 commented 5 years ago

You can try it for the online demo: https://plantain-00.github.io/tree-component/packages/vue/demo/ It that what you expects?

v1r0x commented 5 years ago

The demo works fine. I think it's because you have all your trees on the same level. I have a wrapper around the trees.

<template>
    <div id="some-other-component"></div>
    <tree ...></tree>
</template>

and in my main component I use it like this:

<tree-wrapper :data="..."></tree-wrapper>
<tree-wrapper :data="..."></tree-wrapper>
plantain-00 commented 5 years ago

Trees should share drag target, so maybe your tree-wrapper can expose dragTarget and changeDragTarget

v1r0x commented 5 years ago

I tried to handle dragTarget and change event in my main component, but still no luck. Then, I tried to run a minimalistic example, but this doesn't work either... I used this data (had to add state: {} and children: [] to nodes that did not have them, because I got a lot of errors) and the following component:

<template>
    <div>
        <tree :data="testData" :draggable="true" :drop-allowed="_ => true" :drag-target="dragTarget" @change-drag-target="changeDragTarget" @drop="handleDrop"></tree>
        <tree :data="testData2" :draggable="true" :drop-allowed="_ => true" :drag-target="dragTarget" @change-drag-target="changeDragTarget" @drop="handleDrop"></tree>
        {{ dragTarget }}
    </div>
</template>

<script>
    export default {
        methods: {
            changeDragTarget(e) {
                console.log("change target to:", e);
                this.dragTarget = e;
            },
            handleDrop(data) {
                console.log(data);
            }
        },
        data() {
            return {
                dragTarget: {},
                testData: [...],
                testData2: [...]
            }
        }
    }
</script>

When I select a node, dragTarget is set to it's tree root. When I move the node inside this tree or onto the other, nothing happens in the @change-drag-target event. When I drop the node, @change-drag-target is fired, but the new dragTarget is null :confused:

plantain-00 commented 5 years ago

dragTarget and @change-drag-target just used to share state between different trees. If you want to see what are your drag source data and drop target data, you can get them in @drop

v1r0x commented 5 years ago

Stupid me...Seems like I missed the actual element which handles the drop... :grin: When I drag onto the correct element, drop event is handled with correct sourceData and targetData. Thanks for your help!

One last question: Is it possible to determine if the dropped element is from another tree?

plantain-00 commented 5 years ago

You can add a field in DropData.sourceData.value, or last dragTarget.root, if === current tree data, so drag from current tree.

v1r0x commented 5 years ago

Ok, I simply added the tree id to each node and comparing DropData.sourceData.treeId with DropData.targetData.treeId. Thanks again for the implementation and your help! :tada: Should I close the issue now?

plantain-00 commented 5 years ago

Feel free to close or open the issue, no rules here.