Support dragging multiple elements
See original GitHub issueThere is a common pattern that is hard to implement with native drag and drop: dragging multiple elements. While selection mechanics might vary from app to app (cmd+clicking, checkboxes, predefined groups), but it would be nice to at least make it possible to support this scenario.
Because multiple dragged items may not be siblings in DOM and setDragImage(element, x, y)
is pretty much insane and hasn’t gotten any better, we won’t burden ourselves with trying to render several elements in drag preview at once.
How can we help implement this scenario, if we can’t show a “multiple” drag preview?
In a way, this scenario is already possible: consumers can manually keep track of selected elements, set dragPreview
to some kind of generic placeholder Image
and react appropriately to the dropping of (as far as business logic is concerned) several elements.
However there is currently no supported way for one element to know that it’s part of a group that’s being dragged. From react-dnd’s point of view, if we drag something, this component gets getDragState(type).isDragging = true
, but other components don’t. From your app point of view, if you support multiple selection, you want all logically “selected” items to be aware that they’re being dragged, even if only one of them is being actually “DOM-dragged”.
What we need is a way for components to tell react-dnd that, “hey, although onDragStart
was received by another component, I want to pretend that I’m being dragged too, and have my getDragState(type)
mirror dragged component’s getDragState(type)
, and have my endDrag(didDrop)
called too so I could do my stuff”.
How would components opt into that?
Issue Analytics
- State:
- Created 9 years ago
- Reactions:19
- Comments:32 (8 by maintainers)
Top GitHub Comments
If anyone’s interested, I implemented a multiple drag / grid view: https://codesandbox.io/s/9j897k0mwy. You can use cmd/ctrl and shift keys to select multiple items, then drag them around the grid and insert them anywhere.
This is still a demo, but I might abstract the code a little bit more and package it in a component later.
I implemented it, solution is basically what is described in the first post: