Jack Steam
Jack Steam

Reputation: 5279

How to disable click events for props.children in React?

How can any click events be disabled for props.children?

const Example = props => (
  <div>
    <div>This can be clicked</div>
    {props.children} /* These can't be clicked */
  </div>
)

I am rendering a PDF page using react-pdf and want the user to be able to drag a custom selection marquee (like in Photoshop...). As it is, the PDF page under or inside the marquee element still registers mouse events upon dragging, like text selection.

Upvotes: 2

Views: 5057

Answers (3)

Serge Seredenko
Serge Seredenko

Reputation: 3541

There is an easy, but not robust way to do this:

const Example = props => (
  <div style={{pointerEvents:'none'}}>
    <div style={{pointerEvents:'auto'}}>This can be clicked</div>
    {props.children}
  </div>
)

It is not robust, because if any of the children have pointer-events set to auto, they will be clickable too. See if it fits your needs. Also, it will kill hover and other mouse events.

Upvotes: 5

kirecligol
kirecligol

Reputation: 876

You cannot change the props within an element thus its children props. An alternative solution may be possible with React.cloneElement, Here is a simple peace of code for you:

const Example = props => (
  <div>
    <div>This can be clicked</div>
    {props.children.map((child)=>
        React.cloneElement(child, {
          disabled: true
        })
    )}
  </div>
)

Upvotes: 1

Jack Steam
Jack Steam

Reputation: 5279

Use CSS Grid to put a div on top!

A transparent div rendered on top of another div will intercept click events.

CSS Grid can be used (abused?) to make a single grid area (using grid-template-areas) and assign multiple elements to it (using grid-area).

JSX

const ClickGuard = ({allow, block}) => (
  <div className='click-guard-area'>
    <div className='click-guard-allowed'>{props.allow}</div>
    <div className='click-guard-block' />
    <div className='click-guard-blocked'>{props.block}</div>
  </div>
)

CSS

.click-guard-area {
  display: grid;
  grid-template-areas: 'click-guard';
  height: 100%;
  width: 100%;
}

.click-guard-allowed {
  grid-area: click-guard;
  height: 100%;
  width: 100%;
  z-index: 2;
}

.click-guard-block {
  grid-area: click-guard;
  height: 100%;
  width: 100%;
  z-index: 1;
}

.click-guard-blocked {
  grid-area: click-guard;
  height: 100%;
  width: 100%;
}

Note that ClickGuard expects two props: allow and block. These should be JSX. The React docs explain passing React elements here.

<ClickGuard
   allow={<div>I can be clicked!</div>}
   block={<div>No clicks for me. 😞</div>}
/>

Upvotes: 1

Related Questions