Shopify / draggable

The JavaScript Drag & Drop library your grandparents warned you about.
https://shopify.github.io/draggable
MIT License
17.89k stars 1.1k forks source link

Nested Sortables? #129

Open toanjo opened 6 years ago

toanjo commented 6 years ago

Hi! Great work with this project, it's really good.

I was wondering if nested sortables are a possibility? For example, if I have a list of parent items and child items and I would like to sort the parents between each other or sort their children.

I am using React and have experimented with creating two different sortable objects but haven't been able to make it work as they conflict with one another. Is this not possible at this point or is it my mistake?

Thanks!

tsov commented 6 years ago

Thanks for asking! We are planning to build a NestedSortable module or bake nesting into the existing Sortable module, but this is planned for post stable release. No ETA for this yet unfortunately

Related: https://github.com/Shopify/draggable/issues/56

saluton-mundo commented 6 years ago

This would be awesome, currently using an adapted version of the retired(?) https://github.com/angular-ui-tree/angular-ui-tree . Happy to help with the logic if you'd like

Lewiscowles1986 commented 6 years ago

You have the handle property, so this does support nested drag & drop currently in the event that the parent list at-least has a handle property corresponding to a non-sortable sub-element.

The only problem I'm having is setting this to work nested is when I add another group for sub-items to be transferable between upper level lists. Like a KanBan.

https://codepen.io/Lewiscowles1986/pen/YvgPgP

I did think about adding the selector for the last list, but then the append action is off too. It's just a quick evaluation to see if this is capable of replacing jQuery UI sortable (it's so close).

fdietze commented 6 years ago

Nesting is already possible with the current Sortable:

https://jsfiddle.net/zodqmx09/6/

Lewiscowles1986 commented 6 years ago

It's possible, but a bit of a dead end if you can only sort static elements, not receive new ones. Some form of mutation observer is probably needed.

fdietze commented 6 years ago

You can create and patch the elements with a virtual dom library (like e.g. snabbdom). I just built a nested kanban-board with this technique.

Lewiscowles1986 commented 6 years ago

are there tomes of the internet containing the incantations to work such magic?

fdietze commented 6 years ago

I'm sorry, I don't understand what you intend to say...

beefchimi commented 6 years ago

You can create and patch the elements with a virtual dom library (like e.g. snabbdom). I just built a nested kanban-board with this technique.

@fdietze that sounds really cool! You don't happen to have a repo / example you could point to by chance?

Lewiscowles1986 commented 6 years ago

It's certainly the last time (this week) I'll try asking anything in a funny way.

@fdietze what @beefchimi just said.

fdietze commented 6 years ago

@Lewiscowles1986 I apologize for not getting the joke. I'm not a native english speaker. Please don't stop making humor because of language barriers. :wink:

The kanban board I built is very wired with my project written in Scala, so this would probably not be a helpful example. But I'll try to explain it in more detail here instead:

Just ask, if a step is unclear.

Lewiscowles1986 commented 6 years ago

Hi @fdietze,

I think what I'm doing is probably incompatible with that. For one at the moment I'm not backing anything anywhere so tree structure really doesn't matter (If it's a tree it's a darn special one). I have an example of this working without virtualdom, it just has bugs, it's probably the listening to the sortable:sorted of the Sortable instance that will resolve them. Right now I remove the listeners before adding the sortable and then re-add sortable. that's obviously not ideal should I take it further.

The strange thing is that it works when I have just one instance of Sortable, however I also want to be able to change column order. I think I'll end up just adding nav-button overlay to each to ease the burden of drag-and-drop. It'll achieve the same end result without too much technical debt and up-front decision making.

I started because I'm using WeKan at work. It's heavy for what it is and I'd prefer to store in markdown with a small helper to detect kanban layout. That way it's lightweight and doesn't need a formal storage. One person can be in-charge of full-edits to a board. YMMV

molfar commented 6 years ago

All these examples does not work as expected. Waiting for native nested support very much.

Spone commented 6 years ago

Me too! How can we help?

tlaverdure commented 5 years ago

Any update on this? I tried nesting Sortables, which works, but I'm seeing this error in the console:

screen shot 2018-10-25 at 5 39 37 pm
HectorLS commented 5 years ago

Hi all, same issue here @tlaverdure , did you find any way out of this ? thanks in advance

tlaverdure commented 5 years ago

@HectorLS nope. Just had to do without for now.

HectorLS commented 5 years ago

Hi @travdesjard and all, im having troubles snaping to the nested dropzone, its sorting perfectly between siblings top level, but it gets too much tricky to snap into the nested ones. Any idea why could be ? maybe some css rule 😕 ?

Hope someone can help on this Thanks!

travdesjard commented 5 years ago

@HectorLS would love to help you out but I think this is out of my wheelhouse 😉

molfar commented 5 years ago

Could we hope for implementing nested sortable feature?

stugoo commented 4 years ago

I managed to get a proof of concept working for nested sortables by turning on and off the droppable containers using the events. I attached a data attribute that gets the sortable group and then using the sourceContainer I can determine which groups a sortable element belongs to. From there I just unbind the event to the other containers.

Markup looks a bit like this :

<div class="sortable dashboard" data-sortable-group="dashboard">
  <div class="sortable-item">
    dashboard panel A
  </div>
  <div class="sortable-item">
     <div class="sortable" data-sortable-group="tabs">
        <div class="sortable-item">
            TAB 1
        </div>
        <div class="sortable-item">          
            TAB 2
        </div>
      </div>
  </div>
  <div class="sortable-item">
    dashboard panel C
  </div>
  <div class="sortable-item">
    <div class="sortable" data-sortable-group="tabs">
        <div class="sortable-item">
            TAB X
        </div>
        <div class="sortable-item">          
            TAB Y
        </div>
      </div>
  </div>
  <div class="sortable-item">
    dashboard panel E
  </div>
</div>

And the JS does something like this:

   const groupTargetIdentifier = "data-sortable-group";
   this.droppableContainers = document.querySelector('.sortable');

    this.sortable = new Sortable(this.droppableContainers, {
      draggable: ".sortable-item",
      mirror: {
        constrainDimensions: true,
      },
    });

    this.unwantedContainers = null;
    let group;

    this.sortable.on("drag:start", e => {
      group = e.sourceContainer.getAttribute(groupTargetIdentifier);
      this.unwantedContainers = this.droppableContainers.filter(container => container.getAttribute(groupTargetIdentifier) !== group);
      this.unwantedContainers.forEach(target => this.sortable.removeContainer(target));
    });

    this.sortable.on("drag:stop", () =>{
      this.unwantedContainers.forEach(target => this.sortable.addContainer(target));
      this.unwantedContainers = null;
    });

Maybe not the most performant, but my use case I've got 5 dashboard panels that can be rearranged, and a maximum of 9 tabs

MichaelBrauner commented 2 years ago

Is there any plan to make this work?

Every few months I check the website to see whether the 'nestable' is finally no longer grayed out. As long as that is not possible, we cannot use this library because a very important function is missing. Too bad.

SlimGee commented 8 months ago

Still no PR for this?