1

I have a modal box which has a couple buttons inside. On click outside I want that modal close. I've added ref to the parent element and it's works fine, everything closing when you click outside. But if you click on that buttons inside this modal box , it closes too. How to detect child elements inside this ref and do not allow close modal box?

enter image description here

public handleClickoutside() {
this.props.showMessage()
}

public handleClick = (e) => {
if (this.DOMArrowBox.current !== e.target) {
  this.handleClickoutside()
}
}

public componentWillMount() {
document.addEventListener("mousedown", this.handleClick, false)
}

public componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClick, false)
}

<div className={this.props.className} ref={this.DOMArrowBox}>
    <Social />
    <CallMe className="arrow__box-button" open={this.props.open} />
    <Close
      className="arrow-button_close"
      onClick={this.props.showMessage}
    />
  </div>
Yerlan Yeszhanov
  • 2,149
  • 12
  • 37
  • 67
  • instead this.DOMArrowBox.current !== e.target , try this this.DOMArrowBox.contains(e.target) once – Jayavel Feb 19 '19 at 12:37
  • Possible duplicate of [How to check in Javascript if one element is contained within another](https://stackoverflow.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-contained-within-another) – Hayk Safaryan Feb 19 '19 at 12:41
  • You may Roko's answer helpful: https://stackoverflow.com/questions/14291093/detecting-when-a-user-clicks-outside-a-div?rq=1#answer-14291108 – Jordan Stubblefield Feb 19 '19 at 12:42

3 Answers3

1

You can add a ref on the Button inside modal too and check if the target element is contained within that or not

    public handleClickoutside() {
       this.props.showMessage()
    }

    public handleClick = (e) => {

        if (!this.DOMArrowBox.current.contains(e.target) && !ReactDOM.findDOMNode(this.btnRef.current).contains(e.target)) {
          this.handleClickoutside()
        }

    }

    public componentWillMount() {
        document.addEventListener("mousedown", this.handleClick, false)
    }

    public componentWillUnmount() {
        document.removeEventListener("mousedown", this.handleClick, false)
    }

    <div className={this.props.className} ref={this.DOMArrowBox}>
        <Social />
        <CallMe className="arrow__box-button" ref={this.btnRef}open={this.props.open} />
        <Close
          className="arrow-button_close"
          onClick={this.props.showMessage}
        />
     </div>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
1

I think the best way to resolve this, is to revert the issue : let's imagine that you're not catching the click outside your modal, but the click on the modal background wrapper.

You should wrap your <Modal> into a invisible <Wrapper>, with a lesser z-index than the modal, and with the following styles, to take the parent element/window full width & height :

.modal-wrapper {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1; // has to be < of Modal's z-index
    width: 100%; // or 100vw
    height: 100%; // or 100vh
}

Then, attach the ref on the <Wrapper> and in your handleClick method, replace !== by === (because, remember, we reverted the problem).

Hope this help.

samb102
  • 1,104
  • 5
  • 13
0

Use onBlur event to handle clickoutside. Please, have a look on this answer with working example.

gazdagergo
  • 6,187
  • 1
  • 31
  • 45