how to combine checkbox with text input in reactjs

7.7k views Asked by At

i am trying to build a Ui component in Reactjs which combines a checkbox and a text input attched to it (instead of a text label) so that if the checkbox is checked , the user can change the text input , and if its unchecked the user will not be able to do so the final goal is to render outside of the component all of textinputs valus which left checked as a list or as a menu item. Its should look like this : Checkbox with Text input

anyone knows how should i do this ? im new to reactjs and got a bit confused how to pass logic between two components(as in here between the checkbox and the text input and between the "combo" component and the outer rendered list) . thanks in advance !

EDIT1: well i managed to build the component but i cant make the children call the parent handler (handlerCheckbox , handlerInput)in order to actually make the magic happen.

anything im doing wrong ?

this is the child:

  class CheckboxTxtInput extends React.Component{
constructor(props){
    super(props);
    console.log(props.isChecked)
}

handleCheckboxChild(e) {
    this.props.handleCheckbox(e,this.props.id)
}
handleInputChild(e){
     this.props.handleInput(e,this.props.id)
}
render(){
    return (
        <div>
            <input type="checkbox" onChange={this.handleCheckboxChild} defaultChecked={this.props.isChecked} />
            <input type="text" value={this.props.inputValue} disabled={!this.props.isChecked} onChange={this.handleInputChild}/>
        </div>
    )
}

}

This is the parent:

export default class Text extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        textItems: [{id:0,inputValue:'text',isChecked:true},{id:1,inputValue:'text',isChecked:true}
        ,{id:2,inputValue:'text',isChecked:true},{id:3,inputValue:'text',isChecked:true}]
    };
    this.handleCheckbox = this.handleCheckbox.bind(this);
    this.handleInput= this.handleInput.bind(this);
}
handleCheckbox(e,id) {
    var stateCopy = Object.assign({}, this.state);
    stateCopy.textItems[id].isChecked = e.target.value;
    this.setState(stateCopy);
}

handleInput(e,id){
    var stateCopy = Object.assign({}, this.state);
    stateCopy.textItems[id].text = e.target.value;
    this.setState(stateCopy);
}
render () {
    return (
       <div>
           <hr className="divider-long"/>
           <UI.sectionDividerLabeled label="Show/Hide Text"/>
           <hr className="divider-long"/>
           <p>Here you can show\hide your text</p>
           <div>
               <CheckboxTxtInput id={this.state.textItems[0].id} isChecked={this.state.textItems[0].isChecked}
                                 inputValue={this.state.textItems[0].inputValue} handleInput={this.handleInput}
                                 handleCheckbox={this.handleCheckbox} />
               <CheckboxTxtInput id={this.state.textItems[1].id} isChecked={this.state.textItems[1].isChecked}
                                 inputValue={this.state.textItems[1].inputValue} handleInput={this.handleInput}
                                 handleCheckbox={this.handleCheckbox}/>
               <CheckboxTxtInput id={this.state.textItems[2].id} isChecked={this.state.textItems[2].isChecked}
                                 inputValue={this.state.textItems[2].inputValue}
                                 handleInput={this.handleInput} handleCheckbox={this.handleCheckbox}/>
               <CheckboxTxtInput id={this.state.textItems[3].id} isChecked={this.state.textItems[3].isChecked}
                                 inputValue={this.state.textItems[3].inputValue} handleInput={this.handleInput}
                                 handleCheckbox={this.handleCheckbox}/>
           </div>
               <RenderText />
           </div>

    )
}

}

2

There are 2 answers

2
Chris On

The simplest, React-like way to do this is to have a parent wrapper component - say LabeledCheckbox which contains your Text input and your Checkbox components.

When either of the child components do something, they call a callback provided by the parent, and the parent maintains the state for the two components, passing that state down into the props of both children.

The children in this case would never maintain their own state, instead simply calling callbacks and being prop-fed.

2
Boky On

Create one component with checkbox and input field with the state of the checkbox and text field.

And then you can reuse it where you want.

You can do something like this :

class CheckboxTxtInput extends React.Component{
  constructor(){
       super();

       this.state = {
        checkbox: false,
        inputValue: ""
       }
  }

  handleCheckbox(e){
    this.setState({checkbox: e.target.checked})
  }

  handleInput(e){
    this.setState({inputValue: e.target.value})
  }

  render(){
    return (
        <div>
        <input type="checkbox" onChange={this.handleCheckbox.bind(this)} checked={this.state.checkbox}/>
        <input type="text" value={this.state.inputValue} disabled={this.state.checkbox} onChange={this.handleInput.bind(this)}/>
      </div>
    )
  }
}

class Test extends React.Component {
        render(){
           return (
               <div><CheckboxTxtInput /></div>
           )
        }
}

React.render(<Test />, document.getElementById('container'));

Here is the fiddle.

Hope this helps.