React-beautiful-dnd: Add elements containing data-rbd-is-draggable="false" to default blocked list

Created on 15 Feb 2018  Â·  12Comments  Â·  Source: atlassian/react-beautiful-dnd

Bug or feature request?

Feature request

Currently these elements and tags are being blocked by default:

  • input
  • button
  • textarea
  • select
  • option
  • optgroup
  • video
  • audio
  • contenteditable

I think we are missing 1 more tag which would help a lot to disable drag on specific elements. Simple example is having an element with a menu which appears on hover, there is no easy way to block dragging on menu AFAIK because it's inside draggable element. Would be great if we could disable drag on elements having draggable="false" or similar 🙂

idea 🤔

Most helpful comment

I'm running into this issue, too: I have draggables that contain custom sliders and custom math inputs, neither of which use standard input elements. My current solution is below:

import React from 'react'
import { Draggable } from 'react-beautiful-dnd'

/**
 * PartlyDraggable
 *
 * Temporarily sets isDragDisabled=true when PointerDown event encounters
 * an HTML element that custom isElementDraggable detects as undraggable.
 * isElementDraggable could be customized for other use-cases.
 */
export default class PartlyDraggable extends React.PureComponent {

  state = {
    targetUndraggable: false
  }

  constructor(props) {
    super(props)
    this.rootRef = React.createRef()
    this.onPointerDown = this.onPointerDown.bind(this)
    this.onPointerUp = this.onPointerUp.bind(this)
  }

  static isElementDraggable(element) {
    // Detects MathQuill editable fields
    if (element.classList.contains('mq-editable-field')) {
      return false
    }
    // Detects Ant Design Slider elements
    if (element.classList.contains('ant-slider')) {
      return false
    }
    return true
  }

  static isDragAllowed(top, current) {
    if (top === current) {
      return true
    }
    if (!PartlyDraggable.isElementDraggable(current)) {
      return false
    }
    return PartlyDraggable.isDragAllowed(top, current.parentElement)
  }

  onPointerDown = (event) => {
    const { target } = event
    const rootEle = this.rootRef.current
    if (!PartlyDraggable.isDragAllowed(rootEle, target)) {
      this.setState( { targetUndraggable: true } )
    }
  }

  onPointerUp = () => {
    this.setState( { targetUndraggable: false } )
  }

  render() {
    const { id, isDragDisabled, children, ...otherProps } = this.props
    const { targetUndraggable } = this.state
    return (
      <div
        onPointerDown={this.onPointerDown}
        onPointerUp={this.onPointerUp}
        ref={this.rootRef}
      >
        <Draggable
          key={id}
          isDragDisabled={targetUndraggable || isDragDisabled}
          {...otherProps}
        >
          {this.props.children}
        </Draggable>
      </div>
    )
  }

}

I'm not sure if this is what @alexreadon meant by "patch[ing] the event handlers" but it works well enough for me.

@alexreadon I don't know how common this use-case is (undraggable elements inside draggables) but I was a little surprised there wasn't a simpler solution. Would giving users some way to interact with the isAnInteractiveElement be of interest / acceptable? That could be a list of undraggable custom attributes (empty by default, so no extra DOM manipulations) or some sort of callback function.

All 12 comments

The suggested method for this at the moment is to patch the event handlers to block dragging from custom elements. I am initially hesitate to add any additional queues into the DOM.

I'm running into this issue, too: I have draggables that contain custom sliders and custom math inputs, neither of which use standard input elements. My current solution is below:

import React from 'react'
import { Draggable } from 'react-beautiful-dnd'

/**
 * PartlyDraggable
 *
 * Temporarily sets isDragDisabled=true when PointerDown event encounters
 * an HTML element that custom isElementDraggable detects as undraggable.
 * isElementDraggable could be customized for other use-cases.
 */
export default class PartlyDraggable extends React.PureComponent {

  state = {
    targetUndraggable: false
  }

  constructor(props) {
    super(props)
    this.rootRef = React.createRef()
    this.onPointerDown = this.onPointerDown.bind(this)
    this.onPointerUp = this.onPointerUp.bind(this)
  }

  static isElementDraggable(element) {
    // Detects MathQuill editable fields
    if (element.classList.contains('mq-editable-field')) {
      return false
    }
    // Detects Ant Design Slider elements
    if (element.classList.contains('ant-slider')) {
      return false
    }
    return true
  }

  static isDragAllowed(top, current) {
    if (top === current) {
      return true
    }
    if (!PartlyDraggable.isElementDraggable(current)) {
      return false
    }
    return PartlyDraggable.isDragAllowed(top, current.parentElement)
  }

  onPointerDown = (event) => {
    const { target } = event
    const rootEle = this.rootRef.current
    if (!PartlyDraggable.isDragAllowed(rootEle, target)) {
      this.setState( { targetUndraggable: true } )
    }
  }

  onPointerUp = () => {
    this.setState( { targetUndraggable: false } )
  }

  render() {
    const { id, isDragDisabled, children, ...otherProps } = this.props
    const { targetUndraggable } = this.state
    return (
      <div
        onPointerDown={this.onPointerDown}
        onPointerUp={this.onPointerUp}
        ref={this.rootRef}
      >
        <Draggable
          key={id}
          isDragDisabled={targetUndraggable || isDragDisabled}
          {...otherProps}
        >
          {this.props.children}
        </Draggable>
      </div>
    )
  }

}

I'm not sure if this is what @alexreadon meant by "patch[ing] the event handlers" but it works well enough for me.

@alexreadon I don't know how common this use-case is (undraggable elements inside draggables) but I was a little surprised there wasn't a simpler solution. Would giving users some way to interact with the isAnInteractiveElement be of interest / acceptable? That could be a list of undraggable custom attributes (empty by default, so no extra DOM manipulations) or some sort of callback function.

@alexreardon It might be worth considering as draggable is a standard HTML attribute. I wonder what the implications for doing this is, though.

@dovydaskukalis you could port what @ChristopherChudzicki has above to instead check the draggable attribute.

I will look at this issue when I get back in mid jan 😊
On Wed, 19 Dec 2018 at 8:50 am, Trey Shugart notifications@github.com
wrote:

@alexreardon https://github.com/alexreardon It might be worth
considering as draggable is a standard HTML attribute
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable.
I wonder what the implications for doing this is, though.

@dovydaskukalis https://github.com/dovydaskukalis you could port what
@ChristopherChudzicki https://github.com/ChristopherChudzicki has above
to instead check the draggable attribute.

—
You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
https://github.com/atlassian/react-beautiful-dnd/issues/326#issuecomment-448383579,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACFN7cjef6CFtvs2CJ90BQaKHqUKI-iDks5u6WMVgaJpZM4SGInn
.

We cannot use draggable as it will opt into HTML 5 dnd

Yeah but this is about disabling dragging not opting into it.

(Opting in also requires adding an ondragstart listener).

I am not sure if an attribute is the right way forward. 🤔

I wanted to stay away from the HTML dnd attributes for clarity

Thanks for being proactive on this one. I am hoping to leave this for stability until next year. I have been thinking about an event cancelling pattern also

Perhaps a canStart fn

Any status update on this?

If I'm understanding correctly, this would prevent the dragging of a parent when a child (nested inside parent draghandle) draggable isDragDisabled? Needing this functionality.

@ChristopherChudzicki Your solution is working great for me. Thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

khurram-wasim picture khurram-wasim  Â·  3Comments

vrg-success picture vrg-success  Â·  3Comments

h182032 picture h182032  Â·  3Comments

WJKwok picture WJKwok  Â·  3Comments

alexreardon picture alexreardon  Â·  3Comments