0

can you tell me how can i handle a click on outside of element .For example i have that

<td><input type="number" className="hour" onKeyDown={this.editInlineHour(this)} /></td>

and i want only when i click outside of that element to execute some function and that is it in react !

I try it with that

  window.addEventListener('mousedown', this.pageClick, false);

but even when i click on input field the function is executed.Thanks This is my full code ..basically it is inline edit on field on table.. when i click on that field it show input field.. and i want when i click outside that field do go away

editInlineHour:function () {

    },
    showInlineEditHour:function (i) {
        this.setState({
            index:i,
            showInlineHour:true
        })
    },
    showInlineEditStart:function (i) {
        this.setState({
            index:i,
            showInlineStart:true
        })
    },
    showInlineEditEnd:function (i) {
        this.setState({
            index:i,
            showInlineEnd:true
        })
    },
    pageClick:function () {
      this.setState({
          showInlineStart:false,
          showInlineEnd:false,
          showInlineHour:false
      });
    },
    render: function () {

        var itemMap = this.state.items.map(function (item, i) {
            var fieldDp1;
            if(this.state.showInlineStart){
                fieldDp1 = <input id="inlineDp1"  className="flatpickr" data-date-format="m/d/Y"/>
            }else{
                fieldDp1 = <td onDoubleClick={this.showInlineEditStart.bind(this,i)} ><FormattedDate value={item.startDate}/></td>
            }
            var fieldDp2;
            if(this.state.showInlineEnd){
                fieldDp2 = <input id="inlineDp2"  className="flatpickr" data-date-format="m/d/Y" />
            }else{
                fieldDp2 = <td onDoubleClick={this.showInlineEditEnd.bind(this,i)}><FormattedDate value={item.endDate}/></td>
            }
            var fieldHours;
            if(this.state.showInlineHour){
                fieldHours = <td><input type="number" className="hour" onKeyDown={this.editInlineHour(this)} /></td>
            }else{
                fieldHours =  <td  onDoubleClick={this.showInlineEditHour.bind(this,i)} >{item.workInHours}</td>

            }
            return (
                <tr key={i}>
                    <td><input type="checkbox" checked={item.selected} onClick={this.handleChange.bind(this,i)} /></td>
                    {fieldDp1}
                    {fieldDp2}
                    {fieldHours}
                    <td><label type="button" onClick={this.handleShowModal.bind(this,i)}><img height="30px" src="moliv.jpg"/></label>
                    </td>
                </tr>
            );

        }.bind(this));
        return (
            <div>
                <button className="btn btn-primary center-block" onClick={this.addElem}>Add</button>
                {this.state.list.theList.length > 0 ?  <button className="btn btn-primary" onClick={this.putResult}>Put result</button> :null}
                <table className="table scroll2">
                    <thead>
                    <tr className="danger">
                        <th><input  type="checkbox" checked={this.state.allChecked} onClick={this.toggleAll}/></th>
                        <th>Start Date</th>
                        <th>End Date</th>
                        <th>Hours</th>
                        <th></th>
                    </tr>
                    </thead>
                    <tbody>
                    {itemMap}

                    </tbody>

                </table>
                {this.state.items.length > 0 ? <button  type="button" className="btn btn-danger" onClick={this.deleteItems}>Remove</button> : null}
                <Modal parentState={this.state} modalPropsId={this.props.theProps.id} handleHideModal={this.handleHideModal}/>
            </div>
        );
2
  • Could you provide your full code? Commented Aug 19, 2016 at 8:49
  • Ofc, I edit it and i wrote a little exactly what i want to do Commented Aug 19, 2016 at 8:55

4 Answers 4

1

You can add ref to your element and check if click event comes outside of it.

function handleClickOutside(evt) {
  if (this.refs.yourInput !== evt.target) {
    callSomeFunction();
  }
  return true;
}

componentDidMount() {
  this.clickHandler = handleClickOutside.bind(this);
  document.addEventListener('click', this.clickHandler, true);
} 

componentWillUnmount() {
  document.removeEventListener('click', this.clickHandler, true);
}

In case if you want to check outside click for some component with children, you can use contains

if (!this.refs.yourComponent.contains(evt.target)) {
  callSomeFunction();
}
Sign up to request clarification or add additional context in comments.

Comments

1

Using that approach you will need to assign a onClick handler to your input element and stop propagation so that it doesn't propagate to the windows onClick event.

const handleInsideClick = (e) => {
   e.stopPropagation();
} 

React handles events in a smart way, an event is triggered from the deeper node in the DOM to the top, so when you click in the input you can either stop propagation to the onClick handler in the parent node or do whatever you want in the click event and let it propagate.

6 Comments

Nahh,man it's not working if i assign a onClick event...still it's the same
@FreakProgrammer did you stopped propagation?
No, where i need to write this lines ?
@FreakProgrammer have you read my explanation about the way react handles events? Are you assigning the onClick event to the correct component and preventing the propagation?
@FreakProgrammer if you want to propagation to be stooped for the full table I would assign a function containing that logic I wrote in the top to <table> onClick event
|
0

The event.preventDefault() method stops the default action of an element from happening if that what you're after.

 <td><input type="number" id="inputField" className="hour" onKeyDown={this.editInlineHour(this)} /></td>

JavaScript:

$("#inputField").on("submit", function(event){
      event.preventDefault(); // Stop event 
      event.stopPropagation(); // Stop event (react)
});

http://jsbin.com/nejetoxeve/edit?html,js,console,output

Comments

0

You can wrap Component with a component with a position: fixed like so:

import React, { Component } from 'react';
import ReactDom from 'react-dom';

const styles = (onClick) => ({
  position: 'fixed',
  pointerEvents: onClick ? 'auto' : 'none',
  top: 0,
  bottom: 0,
  right: 0,
  left: 0,
  height: '100%',
});

export default class FixedLayer extends Component {

  static defaultProps = {
    zIndex: 2000,
    onClick: null,
  };

  render () {
    const divProps = { ...this.props };
    delete divProps.zIndex;
    return (
      <div { ...divProps }
        onClick={ (e) => this.props.onClick && (e.target === ReactDom.findDOMNode(this)) && this.props.onClick() }
        style={{...this.props.style, ...styles(this.props.onClick), ...{zIndex: this.props.zIndex}}}>
          {this.props.children}
      </div>
    )
  }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.