atlassian / react-beautiful-dnd

Beautiful and accessible drag and drop for lists with React
https://react-beautiful-dnd.netlify.app
Other
33.39k stars 2.57k forks source link

Support nested list (drag item from parent list into nested child list) #1001

Open josephjesseyoung opened 5 years ago

josephjesseyoung commented 5 years ago

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! πŸ‘

markdon commented 5 years ago

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.

alexreardon commented 5 years ago

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

alexreardon commented 5 years ago

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

alexreardon commented 5 years ago

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

josephjesseyoung commented 5 years ago

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

NeroMorto commented 5 years ago

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’t 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](https://user-images.githubusercontent.com/1481943/49874526-c497c980-fe2f-11e8-896a-06d8647d43cd.png)

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](https://user-images.githubusercontent.com/1481943/49874527-c497c980-fe2f-11e8-92b6-be3973ba8eda.png) ![reordering_nested_list_with_other_elements_2](https://user-images.githubusercontent.com/1481943/49874528-c497c980-fe2f-11e8-8e9c-755ae5f5488e.png) ![reordering_nested_list_with_other_elements_3](https://user-images.githubusercontent.com/1481943/49874530-c5306000-fe2f-11e8-9993-50a65b5c7c5b.png) ![reordering_nested_list_with_other_elements_4](https://user-images.githubusercontent.com/1481943/49874534-c5306000-fe2f-11e8-89a7-f0d476ee0630.png)
  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)

Duohao commented 5 years ago

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

image

Haaxor1689 commented 5 years ago

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

markdon commented 5 years ago

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.

srph commented 5 years ago

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

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 :).

bexoss commented 5 years ago

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.

klickagent commented 5 years ago

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

ZakSingh commented 4 years ago

@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:

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.

Aarbel commented 4 years ago

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

stefanb2 commented 4 years ago

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?

zlanich commented 4 years ago

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!

IlyasArinov commented 4 years ago

+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.

developerruhul commented 4 years ago

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

collab-with-tushar-raj commented 3 years ago

@alexreardon I have similar use cases as well and seems this library is not serving those purposes. I am seriously stuck since more than a week now and hoping the developers should come back at least with an honest response even if otherwise. It seems many people across the globe has such use cases and it is high time that these features should get included in the library. I don't understand why this is not a priority ?? It's been 2 years now and people are asking for it.

hardik98 commented 3 years ago

@alexreardon I am also having similar use case. i am using materil ui treeview for nested view and drag and drop is not working for any child treeview item.It's been 2 years now and people are asking for it.

IlyasArinov commented 3 years ago

@Tush2890 Could be another 2 years until this feature is implemented. I suggest to move on. Check this demo I made that features draggable nested lists using another library (react-sortable-js).

collab-with-tushar-raj commented 3 years ago

@Tush2890 Could be another 2 years until this feature is implemented. I suggest to move on. Check this demo I made that features draggable nested lists using another library (react-sortable-js).

@IlyasArinov I tried your solution and maintained the same hierarchy of DOM nodes as in your demo but after one or two operations, it crashes. After wrapping the parent node with <ErrorBoundary>, this is what I am getting from the library itself :-

image

IlyasArinov commented 3 years ago

@Tush2890 I am not sure what the problem is. All I can say is that I use this library pretty extensively with infinite nested children lists and dragging from another lists, and It works just fine (except It does not rerender on props change, but there is a workaround for that).

Harsh298 commented 3 years ago

@IlyasArinov does this library support combine feature same as React beautiful dnd provides ?

IlyasArinov commented 3 years ago

@Harsh298 Not exactly combine feature, but with the original library, on which react-sortable-js is based, you can multidrag using plugins. I haven't tested it, though.

Harsh298 commented 3 years ago

@Harsh298 Not exactly combine feature, but with the original library, on which react-sortable-js is based, you can multidrag using plugins. I haven't tested it, though.

@IlyasArinov what i mean by combine is you can drag Item A and put it over item B when drag and over you can get both item A and B and you can perform move or copy functionality. Like how generally works in google drive or any file managers. Where you can drag folder and combine/merge/move to another folder. So is react sortable js provides that kind of combining functionality where i can get both ids ?

mmahalwy commented 3 years ago

Still nothing here? :(

shubham799 commented 2 years ago

You can find here for the nested list dragging child from one parent to another.