react-arborist icon indicating copy to clipboard operation
react-arborist copied to clipboard

Reordering does not work when drop is disabled

Open krillboi opened this issue 2 years ago • 2 comments
trafficstars

First of all, thanks for this library, it's great!

I am struggling to figure out how to get the following DnD behaviour to work properly with the following tree:

  • Root1
  • Root2
  • Root3
    • Child1
    • Child2
  • Root4
    • Child3
    • Child4
  1. Roots should not be allowed to be dragged into each other
  2. Reordering roots at the same level should still be allowed

If I provide the disableDrop handler with something like:

  if (parentNode.level >= dragNodes[0].level) {
    return true;
  }
  return false;

Then the roots are no longer allowed to be dragged into each other but also reordering is no longer working properly - it seems that I can only reorder in between roots with children (for example drag Root1 in between Root3 and Root4) or drag a root all the way to the top or bottom.

Am I using this correctly?

krillboi avatar Jul 31 '23 08:07 krillboi

Hi! Thanks for using the library. I believe it is possible by passing a function to the disableDrop prop.

((args: {
        parentNode: NodeApi<T>;
        dragNodes: NodeApi<T>[];
        index: number;

The parent node is the "folder" your dragging over. The index is the place within the folder you will drop. And the dragNodes are the nodes you are dragging.

So you maybe need to check if the dragNode.parentId === parentId. Then allow drop only if that is true?

Checkout the Node api. Those are all the methods you can call on the dragNodes.

Please report back if that works for you.

jameskerr avatar Jul 31 '23 16:07 jameskerr

Thanks for the reply @jameskerr. I haven't been able to figure it out yet completely, but I am unsure if I've found a bug. The following code almost works (also brings the behavior I want for folders further down the tree):

  const dragNode = dragNodes[0];
  if (dragNode.isInternal) {
    if (parentNode.level < dragNode.level) return false;
    return true;
  }
  return false;

This works most of the way but once again, only works if I drag Root1 in between Root3 and Root4. In this scenario parentNode.level becomes -1 with an id of __REACT_ARBORIST_INTERNAL_ROOT__ which allows the root to be dropped in between. But if I drag Root1 in between Root2 and Root3, parentNode.level stays 0 and the drop is disallowed. It seems this is dependent on whether or not the internal node has any children or not - if the children array contains any objects, the level becomes -1 and if the array is empty it stays 0.

krillboi avatar Aug 01 '23 09:08 krillboi