Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to prevent drag/drop behaviour from being triggered from within Draggable? #1810

Open
zachsa opened this issue Apr 7, 2020 · 10 comments

Comments

@zachsa
Copy link

zachsa commented Apr 7, 2020

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.

@chuckWu1989
Copy link

@zachsa I created a related PR to solve this problem: #1764

Here is the issue: #1722

@zachsa
Copy link
Author

zachsa commented Apr 7, 2020

Thanks @chuckWu1989 . Keen to be able to achieve this!

@chinanderm
Copy link

chinanderm commented May 15, 2020

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.

@kreja
Copy link

kreja commented Feb 19, 2021

Having the same problem. I've tried to stop event propagation in onClick, onMouseDown, onMouseMove, onDrag, onDragCapture, onDragStart, onDragStartCapture, but none of them worked.

@skang
Copy link

skang commented May 26, 2021

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.

@paveltretyakovru
Copy link

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>

@Merlin04
Copy link

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

@zhaochengxian
Copy link

@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

@dexkode4
Copy link

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

This worked for me

@DevPowers
Copy link

DevPowers commented May 10, 2023

@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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants