React-beautiful-dnd: Support nested list (drag item from parent list into nested child list)

Created on 11 Dec 2018  路  18Comments  路  Source: atlassian/react-beautiful-dnd

Bug or feature request?

Feature request

Feature request

First of all, amazing work here, kudos to the developers! 馃憤 馃憤

I've been using this library to develop a React based UI builder. In my use case, I need the sortable feature to work in a nested element. However I noticed in the readme,

"Independent nested lists - a list can be a child of another list, but you cannot drag items from the parent list into a child list"

Currently, my work around for this problem is to use the combine feature with nested element so that an element could go inside another element in the same hierarchy and be the child of that element. However, again, I also noticed that the combine feature only works on elements in the same hierarchy (ex: items from a list cannot be combined with items from a nested list and vice versa).

Is there a plan for the nested list so that items could be dragged everywhere regardless of the nested list level? I think this could be beneficial for some use case.

Sorry for my bad english 馃槃 and thanks again! great work! 馃憤

docs 馃摉 help wanted 馃憢

Most helpful comment

Hello there!
I'm trying to solve the same problem too.

As it seems to me, within the current functionality, it is possible to keep track where (parent or nested list) is current item is being dropped.
On the other hand, creating nested lists can also be done dynamically, based on a new "combine" feature. The union itself can be tracked through the result object's property combine in onDragEnd method. After that, the combined elements can be rendered as a nested list according to changes in app's state.

But on the way to this solution, I faced a number of problems with the animation of moving items from a nested list to the parent.
At first, I tried my implementation - I came across a problem with animation that I could not to solve.
Then I found that there is an ideologically similar example in StoryBook
I made an example by analogy, and also faced the same problems of animation. After that, I decided to check the problem existence on the original example, and was able to reproduce it.

To reproduce the current situation with an example, it is necessary to remove the type attribute in stories/src/vertical-nested/quote-list.jsx:56 (line number) or make it static (for example, 'list').

<Droppable droppableId={list.id} /* type={list.id} */ key={list.id}>

This is necessary for the droppable zones to be of the same type (if I don鈥檛 confuse anything, then this is a requirement for moving elements (draggable) between the droppable zones).

If everything described above is ideologically correct, then I face the following problems. This is not all of them, but the most "visually incorrect".

  1. When you try to move an item from a nested list to parent, the next animation problem appears when the item is not under the cursor.
    This behavior appears only when we want to move the item above the nested list. If you move it down, then everything looks fine.
    Screenshot

moving_element_from_nested_list_to_parent

  1. There are a number of problems with sorting items (including nested lists).

2.1. Dropout of elements from a nested list when trying to re-sort a nested list within a parent.

Screenshot

reordering_nested_list_with_other_elements_0


2.2. Incorrect behavior of elements under a nested list. With a small movement of the cursor with a nested list, you can see the situation when the elements of the parent list jump by a group or one by one at a time.
Screenshots

reordering_nested_list_with_other_elements_1
reordering_nested_list_with_other_elements_2
reordering_nested_list_with_other_elements_3
reordering_nested_list_with_other_elements_4

  1. Sometimes it is difficult to insert an item between a nested list and a parent item.
    Screenshot

trying_to_drop_item_from_parent_to_nested_list

Also, in the process of developing the first prototype, I thought about rerendering an element when it is in state isOnDragging, but faced the fact that this is not possible.
It seems to me that it would be helpful for nested list with a large elements count, since in this case it may not be convenient to keep track of the items under this list. An ability to rerender a large list into a small element, with an appropriately sized placeholder (for a new small element) would solve such a problem. And may be in some other cases.

Right now these are the main problems I have encountered.

Thx for your lib and sorry for my English)

All 18 comments

This is something I've had to look at too. Instead of having nested droppables/lists you can instead have one droppable with a 'flat' list of all of your draggables and handle their tree/structure separately. This is what I saw @atlaskit/tree doing and have partially built my own implementation.

It makes calculating the new position and parent a bit harder (I haven't done it yet 馃槄) , but in the end it might give some advantages. Virtualization/Windowing looks easier with a flat DOM tree.

Thanks @markdon!! Yes, that is now @atlaskit/tree works. It is technically a flat structure

It could be nice to create a general guide for how to achieve this

If somebody wants to go on a journey and document it - it would be great to add as a guide to this project

Thanks for the fast reply!! @markdon @alexreardon. Going to try the tree structure and see what I can find

Hello there!
I'm trying to solve the same problem too.

As it seems to me, within the current functionality, it is possible to keep track where (parent or nested list) is current item is being dropped.
On the other hand, creating nested lists can also be done dynamically, based on a new "combine" feature. The union itself can be tracked through the result object's property combine in onDragEnd method. After that, the combined elements can be rendered as a nested list according to changes in app's state.

But on the way to this solution, I faced a number of problems with the animation of moving items from a nested list to the parent.
At first, I tried my implementation - I came across a problem with animation that I could not to solve.
Then I found that there is an ideologically similar example in StoryBook
I made an example by analogy, and also faced the same problems of animation. After that, I decided to check the problem existence on the original example, and was able to reproduce it.

To reproduce the current situation with an example, it is necessary to remove the type attribute in stories/src/vertical-nested/quote-list.jsx:56 (line number) or make it static (for example, 'list').

<Droppable droppableId={list.id} /* type={list.id} */ key={list.id}>

This is necessary for the droppable zones to be of the same type (if I don鈥檛 confuse anything, then this is a requirement for moving elements (draggable) between the droppable zones).

If everything described above is ideologically correct, then I face the following problems. This is not all of them, but the most "visually incorrect".

  1. When you try to move an item from a nested list to parent, the next animation problem appears when the item is not under the cursor.
    This behavior appears only when we want to move the item above the nested list. If you move it down, then everything looks fine.
    Screenshot

moving_element_from_nested_list_to_parent

  1. There are a number of problems with sorting items (including nested lists).

2.1. Dropout of elements from a nested list when trying to re-sort a nested list within a parent.

Screenshot

reordering_nested_list_with_other_elements_0


2.2. Incorrect behavior of elements under a nested list. With a small movement of the cursor with a nested list, you can see the situation when the elements of the parent list jump by a group or one by one at a time.
Screenshots

reordering_nested_list_with_other_elements_1
reordering_nested_list_with_other_elements_2
reordering_nested_list_with_other_elements_3
reordering_nested_list_with_other_elements_4

  1. Sometimes it is difficult to insert an item between a nested list and a parent item.
    Screenshot

trying_to_drop_item_from_parent_to_nested_list

Also, in the process of developing the first prototype, I thought about rerendering an element when it is in state isOnDragging, but faced the fact that this is not possible.
It seems to me that it would be helpful for nested list with a large elements count, since in this case it may not be convenient to keep track of the items under this list. An ability to rerender a large list into a small element, with an appropriately sized placeholder (for a new small element) would solve such a problem. And may be in some other cases.

Right now these are the main problems I have encountered.

Thx for your lib and sorry for my English)

http://www.bootcss.com/p/layoutit/ @alexreardon , dnd can not do something like this ?

image

Can anyone provide source or at least working example of tree drag and drop with react-beautiful-dnd and @atlaskit/tree?

Can anyone provide source or at least working example of tree drag and drop with react-beautiful-dnd and @atlaskit/tree?

There's the atlaskit example here.

@atlaskit/tree can't drag between trees, but it doesn't require a huge amount of changes to make it happen. I came up with something that suits my use shown here.

I'm not sure if this has been pointed out before, but this seems to be a valid use-case for nested connected droppables (vertical > horizontal) :

Frame

  • Widget -> New row
  • Widget -> Existing row; new column
  • Column -> New row
  • Row -> New column

I'm sure this is rather complex to implement (plus it's not in the roadmap). Anyway, just leaving this here. Thanks for all your work @alexreardon :).

I was trying to implement these features during a few days, But I couldn't catch up using @atlaskit/tree and react-beautiful-dnd together. But I found a proper project today. For anyone like me I suggest to use this project: https://github.com/frontend-collective/react-sortable-tree. It is able to drag-and-drop over parent-child, and support copy behaviors.

I was trying to implement these features during a few days, But I couldn't catch up using @atlaskit/tree and react-beautiful-dnd together. But I found a proper project today. For anyone like me I suggest to use this project: https://github.com/frontend-collective/react-sortable-tree. It is able to drag-and-drop over parent-child, and support copy behaviors.

unfortunately it does not support touch devices properly

@alexreardon can I ask what the underlying limitation is that prevents dragging from a nested list to an outer list and vice-versa? For our use case it's a requirement (we can't flatten our tree structure due to some other limitations). Most people probably don't need this feature, so we'd be fine forking the library. It would be super helpful if you could point us towards what the cause is so we have a place to start!

Update

What I know so far from playing around with the code:

  • Step one is to set the parent and child list to accept the same type
  • The main issue seems to be that dragging a child list's card up into its parent causes a visual displacement in both the child and parent lists. This is because the card being dragged "teleports" down to be at the relative position it should be at in the parent, but in the child, creating a displacement there too. It's kind of hard to explain, so here's an image. My mouse is where the open space is in the parent:
    image
  • From what I can tell, the marginBox is being calculated incorrectly and teleports the item visually back down to the child list (if I remove the top: property in chrome devtools it goes to (what I think is) the correct position and fixes most of the issues for this case, but of course breaks normal repositioning). Weirdly, as far as I can tell, the redux store has the correct values for displacements/positioning even though there's two simultaneous displacements happening in both the child and parent list. I'm missing something here, but I'm not sure what.
  • As a side note, dragging from a child list down (forwards) into the parent list works perfectly.

So, in summary, it looks like the solution would (at least partially) be an extra case that needs to be handled in wherever the marginBox is calculated, but I can't seem to figure out where that is / how that works.

@alexreardon do you plan to fix this issue ? Thanks for your help !

Running into the same issue with a recursive data structure of same type of objects, i.e. Object has a property that is of type Object[]. I really I would like to be able to move them between levels :-/

I also have played around with react-dnd and one difference is the nesting behaviour of react-beautiful-dnd Droppable's of the same type=:

<Droppable droppableId="0" type="TYPE" ...>
   ...
   <Droppable droppableId="0.0" type="TYPE" ...>
      ...
   </Droppable>
   ...
   <Droppable droppableId="0.1" type="TYPE" ...>
      ...
      <Draggable draggableId="0.1.0" ...>
         ...
      </Draggable>
      ...
   </Droppable>
   ...
</Droppable>

In the above example Draggable is of TYPE. react-beautiful-dnd will only offer you to drop it into Droppable 0, i.e. the outer Droppable takes priority over any inner one of the same type. Dropping into sibling Droppable's of the same type, i.e. ones that are not wrapped by a Droppable of the same type, works fine.

In react-dnd the behaviour is exactly the opposite: as long as you are within the inner droppable you can drop it there, otherwise it goes to the outer one. (Unfortunately react-dnd has many issues/quirks/bugs under Chrome (or vice versa), which is a deal-breaker for my project...)

I haven't looked into the code, but I'm making an educated guess that when Draggable of TYPE is being dragged then a tree search is performed that stops at the first Droppable of TYPE. Would it be possible to add a property that would enable a depth-first search, i.e. the inner Droppable would take priority over the outer one?

I too desperately need tree support, and the ability to drag items between different levels. I'm seeing that this is still not supported, and I cannot get it to work either. I prefer not to use the Atlaskit tree library, as I'm needing this for various different use cases that don't line up well with that library's opinions. Any update on this? Thanks!

+1 here. Would really appreciate this.
As for those who need nested draggable lists asap as I do, it's worth looking into react-sortable-js and react-dnd. These are the examples, that I've found:

Personally, I think i'm gonna explore sortable-js, and hope that someday some genius will figure this one out.

so no hope for a nested/tree-like list in react-beautiful-dnd?

Was this page helpful?
0 / 5 - 0 ratings