Sortable icon indicating copy to clipboard operation
Sortable copied to clipboard

Nested list (tree) - how to nest elements by dragging to the right?

Open ddenev opened this issue 5 years ago • 10 comments

I am using the Vue.Draggable binding for SortableJS to build a draggable tree structure.

I built the tree and DnD works just fine. Now I want to implement nesting a node by dragging it horizontally to the right, under the node that I want to nest it into.

Here is my question about that on Stackoverflow (the Vue.Draggable dev requires such questions to be asked on Stackoverflow but I still haven't received any answer there). So I ask here since I believe that if that feature would be supported by SortableJS then it would also work in Vue.Draggable.

What would be the approach with Vue.Draggable/SortableJS in order to achieve the functionality as shown in this animated gif? H7U5D

The default behavior of Sortable for nesting is to drag the element up to the above element until the mouse reaches emptyInsertThreshold pixels from the drop zone of the above element but I would like to be able to nest elements by dragging them to the right. Same for un-nesting.

I have set emptyInsertThreshold to 0 to disable the default behavior and now when I drag the element to the right I get the following events fired: clone and start (in that order).

But how do I:

  1. Can get notified when the mouse has traveled the pre-defined distance to the right?
  2. Inform Vue.Draggable that the ghost element should be nested as a child to the element under which I am doing the horizontal movement?

ddenev avatar Dec 27 '19 11:12 ddenev

@drank There are nested list examples with code in the vue-draggable repository. Two examples can be found at https://sortablejs.github.io/Vue.Draggable/#/nested-example.

waynevanson avatar Dec 29 '19 07:12 waynevanson

@waynevanson , thank you for replying.

I am aware of all the Vue.Draggable and SortableJS examples but none of them covers the use case that I have described above. I have done quite a (re)search on the approach but couldn’t find anything which is based on Vue.Draggable/SortableJS, that is why I finally decided to ask here, hoping that someone might have a solution (or at least a guidance) to the problem.

ddenev avatar Dec 30 '19 20:12 ddenev

The example that you refer to above shows the default way SortableJS approaches nesting. I know about it and I know how to make it work but I need another approach - described and shown in my OP.

ddenev avatar Dec 30 '19 21:12 ddenev

Dear @waynevanson

Could you please at least tell me if SortableJS is capable of doing this? I am still unable to find out how to approach this problem with SortableJS that's why I need some help - I guess you would definitely know better as the author of the library :)

ddenev avatar Jan 13 '20 12:01 ddenev

The default behavior of Sortable for nesting is to drag the element up to the above element until the mouse reaches emptyInsertThreshold pixels from the drop zone of the above element but I would like to be able to nest elements by dragging them to the right. Same for un-nesting

@drank Apologies, I see what you mean. This isn't implemented in Sortable as a feature. I would also like this.

I'm hoping that in the coming years when we finish the typescript conversion, we can trigger state changes by calling a sortable.[move]() function

waynevanson avatar Jan 15 '20 21:01 waynevanson

@drank Sorry I didnt respond to the reply you left on my answer. Here is my answer regarding the onmove: You can use custom dragover events that will be fired during Sortable's drag instead (see: https://stackoverflow.com/questions/54917268/ondragover-equivalent-in-vue-draggable-sortable-js/54960057#54960057)

owen-m1 avatar Jan 16 '20 14:01 owen-m1

I think there is another way to do this (to generate a new level of tree). The animation is not the same but I think it's do-able and perhaps even more user friendly, please correct me if I'm wrong:

Lets say we have a nested tree like this

<ol>
<li>
1
<ol>
<li>1.1</li>
<li>1.2</li>
</ol>
</li>
<li>
2
</li>
<li>
3
</li>
</ol>

Let's say that I want to drag 1.2 inside 1.1 to make it 1.1.1 instead, then perhaps I can do:

  1. Listen to onStart
  2. Add a placeholder, droppable placeholders for all items that do not have children yet (or we can be smart and only add on the same tree that the dragging item is moving on)
  3. Capture onEnd and see if we are dropping on a placeholder which means we should actually add a new level

yellow1912 avatar Feb 06 '20 13:02 yellow1912

  • Listen to onStart
  • Add a placeholder, droppable placeholders for all items that do not have children yet (or we can be smart and only add on the same tree that the dragging item is moving on)
  • Capture onEnd and see if we are dropping on a placeholder which means we should actually add a new level

Can you provide a demo for this? @yellow1912

ThisIsntMyId avatar Feb 10 '20 06:02 ThisIsntMyId

Let's take this list for example: https://sortablejs.github.io/Vue.Draggable/#/nested-with-vmodel

Currently the problem is that when all the nested prerequisites are met, attempting to indent item donkey by dragging only works if the cursor drags right to the top of the ghost element.

It feels like Sortable doesn't track tangentially: no tracking of the horizontal positioning if we're in a vertical list. The same applies to vertical tracking on horizontal lists.

I feel like Sortable should detect how deep we're indenting. If there is a nested sortable inside that the item could move to, then the dragging element to it.

Adding another plane WILL cause some issues to current, so this is not the easiest feature to implement.

waynevanson avatar Apr 21 '20 00:04 waynevanson

Hi, is there any progress about this feature? Looking forward about this nested list by dragging element to the right. So far I see ui-sortable library (with jQuery plugin) has this feature. Currently, I'm looking for non jQuery plugin like SortableJS to fulfill this case.

kresnasatya avatar Dec 27 '21 05:12 kresnasatya