amsik / liquor-tree

Tree component based on Vue.js
MIT License
398 stars 95 forks source link

When dragging children, copy parent alone #202

Open Darkkkkkkk opened 4 years ago

Darkkkkkkk commented 4 years ago

Hello,

I have a tree list that is structured in the following manner:

My tree list supports drag and drop. My problem is related to DnD.

I am trying to achieve the following: when moving an article and dragging it directly into a category, in order to respect the aforementioned nesting rules (category > event > article) I want to copy the article's parent (an event) along. The parent of the selected article, that event, will have as children only the dragged article, even if the event initially had more childrens.

Let's recap, I drag an article directly into a category. The result should be that I get the article moved and it's parent is being copied to the new category. The previous parent remains unmodified except the fact that the element children is not its children anymore. When copying/bringing along the event, no other child will be brought along. Also a gif that shows what I am working on - https://im5.ezgif.com/tmp/ezgif-5-212acf049e23.gif

I managed to achieve the following: initially the tree works flawlessly, until I drag an article into another category. Then dragging stops working and the console gets filled with errors.

I've done the following edits DndMixin.js

      if(this.draggableNode && this.draggableNode.node.data.typeOfNode == 0 && this.$$dropDestination.data.typeOfNode == 2) {
        let articleID = this.draggableNode.node.data.id; // the original article dragged
        this.draggableNode.node = this.draggableNode.node.parent;
        // replacing the original article with it's parent, the event
        this.draggableNode.node.children.forEach((item, index) => {
          if(item.data.id == articleID) {
            onlyChildren = index;
          }
        })
        typeOfInteraction = 1;
        delete this.draggableNode.node.id;
      }

I am storing the index as onlyChildren and passing it toward Node.js here: this.draggableNode.node.finishDragging(this.$$dropDestination, auxDropPosition, typeOfInteraction, **onlyChildren**);

Finally, in Node.js, my finishDragging functions looks like this:

finishDragging (destination, destinationPosition, typeOfInteraction, onlyChildren) { if (!destination.isDropable() && destinationPosition === 'drag-on') { return } debugger; const tree = this.tree const clone = this.clone() const parent = this.parent

clone.id = this.id
tree.__silence = true

let wasNull = false;
if(tree.activeElement == null) {
    wasNull = true;
    tree.activeElement = parent.children[0].children[onlyChildren];
}

if(typeOfInteraction == 0){
    this.remove()
} else {

    tree.activeElement.parent.children.splice(0, 1);

    let aux = clone.children.map((item, index) => {
        if(index == onlyChildren) {
            return item;
        }
    });
}

if (destinationPosition === 'drag-on') {
  tree.append(destination, clone)
} else if (destinationPosition === 'drag-below') {
  tree.after(destination, clone)
} else if (destinationPosition === 'drag-above') {
  tree.before(destination, clone)
}

destination.refreshIndeterminateState()

parent && parent.refreshIndeterminateState()
tree.__silence = false

clone.state('dragging', false)
this.state('dragging', false)
// need to call emit on the clone, because we need to have node.parent filled in the event listener
clone.$emit('dragging:finish', destination, destinationPosition)

if (clone.state('selected')) {
  tree.selectedNodes.remove(this)
  tree.selectedNodes.add(clone)

  tree.vm.$set(this.state, 'selected', false)
  tree.vm.$set(clone.state, 'selected', true)
}

if (this.tree.options.store) {
  this.tree.vm.$emit('LIQUOR_NOISE')
}

}

I suppose when I move the article and replace it with its parent the event I get to 'destroy' some sort of order of the list because no dragging works afterward. What would be the correct approach?