react-beautiful-dnd
react-beautiful-dnd copied to clipboard
How to prevent drag/drop behaviour from being triggered from within Draggable?
Using
<Draggable>
<div>
... lots of children
<div id="slider">
</div>
</Draggable>
I would like to be able to stop the drag and drop from happening when div#slider
is interacted with. To do this, my current idea is to wrap div#slider
inside a element that stops event propagation. So:
Expected behavior
const handler = e => e.stopPropagation()
<Draggable>
<div onClick={handler} onMouseDown={handler} ... etc.>
<div id="slider" />
</div>
</Draggable>
But having tried handling quite a number of different events at this point, I can't figure out which events are propagating. Surely there must be a way to just stop whatever event is triggering the drag/drop interaction?
If so, please let me know. I would also like to know if this isn't simple - from Chome Dev Tools it looks like the drag animation is actually handled by workers. But I'm out of my depth here.
If there was mention on how the drag/drop interaction works, or where to find that information, that would be helpful.
Actual behavior
This information is seemingly not easily accessible. Or if it is, I don't know how to find it.
Suggested solution?
Extending the README / docs slightly.
@zachsa I created a related PR to solve this problem: https://github.com/atlassian/react-beautiful-dnd/pull/1764
Here is the issue: https://github.com/atlassian/react-beautiful-dnd/issues/1722
Thanks @chuckWu1989 . Keen to be able to achieve this!
If I'm understanding correctly, looking forward to this as well!
I have the following structure and want to prevent a drag on Draggables of type A when a Draggable of type B where isDragDisabled
is trying to be dragged. The drag handle for DraggableA is the entire element, which houses n number of DraggableBs:
<DragDropContext>
<Droppable type="A">
<Draggable>
<div {...provided.dragHandleProps}>
<Droppable type="B">
<Draggable />
<Draggable isDragDisabled={true} />
<Draggable />
<Draggable />
</Droppable>
</div>
</Draggable>
<Draggable>
...
</Draggable>
<Draggable>
...
</Draggable>
</Droppable>
</DragDropContext>
Currently, when trying to drag draggable of type B that has isDragDisabled, draggable of type A starts being dragged.
Having the same problem. I've tried to stop event propagation in onClick
, onMouseDown
, onMouseMove
, onDrag
, onDragCapture
, onDragStart
, onDragStartCapture
, but none of them worked.
This is highly wanted in my situation - I need to disable drag-capturing inside a draggable on some of its children elements to make other interaction handling possible.
I have observe that if I skip referal link to droppable element then all draggable elements have a none draggable state.
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<StyledTable
{...provided.droppableProps}
ref={draggable ? provided.innerRef : null}
>
// ....
</StyledTable>
)}
</Droppable>
For anyone still trying to get this to work, I figured out a terribly hacky way to prevent dragging on any child element of a Draggable
:
/* provided is the object with provided props from the Draggable */
<div
data-rbd-drag-handle-context-id={provided.dragHandleProps?.["data-rbd-drag-handle-context-id"]}
data-rbd-drag-handle-draggable-id="gibberish"
style={{
// When you set the data-rbd-drag-handle-context-id, RBD applies cursor: grab, so we need to revert that
cursor: "auto"
}}
/>
The way RBD starts a drag (at least I think) is by listening for global mousedown
events, then identifying the element that was clicked/dragged. Once it has the element, it searches in its parents for an element with data-rbd-drag-handle-context-id
set to the corresponding id. Then, it references that element's data-rbd-drag-handle-draggable-id
to figure out what's being dragged. If we set the context-id
to the actual value but set the draggable-id
to gibberish, RBD will error when you try to drag the div (since it can't find the corresponding Draggable
) and abort the entire drag and drop process, which is exactly what we want (minus the error printed in the console, which should only show up in dev mode).
@zachsa I created a related PR to solve this problem: #1764
Here is the issue: #1722
You two are not talking about the same problem
For anyone still trying to get this to work, I figured out a terribly hacky way to prevent dragging on any child element of a
Draggable
:/* provided is the object with provided props from the Draggable */ <div data-rbd-drag-handle-context-id={provided.dragHandleProps?.["data-rbd-drag-handle-context-id"]} data-rbd-drag-handle-draggable-id="gibberish" style={{ // When you set the data-rbd-drag-handle-context-id, RBD applies cursor: grab, so we need to revert that cursor: "auto" }} />
The way RBD starts a drag (at least I think) is by listening for global
mousedown
events, then identifying the element that was clicked/dragged. Once it has the element, it searches in its parents for an element withdata-rbd-drag-handle-context-id
set to the corresponding id. Then, it references that element'sdata-rbd-drag-handle-draggable-id
to figure out what's being dragged. If we set thecontext-id
to the actual value but set thedraggable-id
to gibberish, RBD will error when you try to drag the div (since it can't find the correspondingDraggable
) and abort the entire drag and drop process, which is exactly what we want (minus the error printed in the console, which should only show up in dev mode).
This worked for me
@Merlin04 Thanks! That is indeed terribly hacky, but it works so idc and it's also kind of brilliant lol as I'm sure that required some digging to figure out, appreciate you posting your finding !! <3