jason1234
jason1234

Reputation: 213

Using Select to control Input

I have two textboxes which has a default value of 25. I have 2 buttons; increment by 1 and decrement by 1. I do not want to manual key in the values of the textboxes, as such, I wanted to create a dropdown select to control the values of the textbox. This is how it looks like:

enter image description here

Is it possible to bind the textboxes with the select? Additional Question: Is it possible to have one [value,setValue] to control both inputs?

This is my code:

const { useState } = React;

function MyApp(){
  const [value1, setValue1]= useState(25)
  const [value2, setValue2]= useState(25)
  function increment(){
     if(selected_id == 1){ //not sure how to implement
        setValue1(value1+1)
     }
     else{
        setValue2(value2+1)
     }
  }    
  function decrement(){
     if(selected_id == 1){ //not sure how to implement
        setValue1(value1-1)
     }
     else{
        setValue2(value2-1)
     }
  }    
  return(
    <div id="react">
       <div>
         Textbox1: <input id="1" defaultValue="value1"/>
         Textbox2: <input id="2" defaultValue="value2"/>
       </div>
       <div>
          <select defaultValue="Textbox1"/>
          <button onClick={increment}> Increment </button>
          <button onClick={decrement}> Decrement </button>
       </div>
    </div>
  )
}

ReactDOM.render(
    <MyApp />,
    document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

Upvotes: 2

Views: 105

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1073998

If I understand correctly, you want the select to choose which text box the Increment and Decrement buttons control. If so, then yes it's possible to do that, but no you can't have one value for both text boxes since by definition, they'll contain different values sometime.

To have the select control the buttons, you'd add a piece of state that tells the buttons what to update:

const { useState } = React;

function MyApp() {
    const [value1, setValue1] = useState(25);
    const [value2, setValue2] = useState(25);
    // The state telling us which text box to update
    const [chosenTextBox, setChosenTextBox] = useState(1);
  
    function increment(){
        // Update the relevant box
        if (chosenTextBox === 1) {
            setValue1(v => v + 1);
        } else {
            setValue2(v => v + 1);
        }
    }    
  
    function decrement(){
        if (chosenTextBox === 1) {
            setValue1(v => v - 1);
        } else {
            setValue2(v => v - 1);
        }
    }    
  
    return(
        <div id="react">
             <div>
                 Textbox1: <input id="1" value={value1} onChange={e => setValue1(+e.target.value)} />
                 Textbox2: <input id="2" value={value2} onChange={e => setValue2(+e.target.value)} />
             </div>
             <div>
                  <select value={chosenTextBox} onChange={e => setChosenTextBox(+e.target.value)}>
                      <option value="1">Textbox 1</option>
                      <option value="2">Textbox 2</option>
                  </select>
                  <button onClick={increment}> Increment </button>
                  <button onClick={decrement}> Decrement </button>
             </div>
        </div>
    )
}

ReactDOM.render(
    <MyApp />,
    document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

A couple of notes on that:

  • You need to tell the text boxes what their values are. I've used value={value1} and such above.
  • Although with the code above you'd be okay using setValue1(value1 + 1) because of the specific way the state changes in that component, I recommend defaulting to using the callback style anyway. In more complex components that get their state changed in other ways, it can matter.
  • We could use arrays if there were going to be more than just a couple of text boxes

Just for the fun of it, that array approach:

const { useState } = React;

function MyApp() {
    // The values -- the length of the array dictates how many text
    // boxes there are
    const [values, setValues] = useState([25, 25, 25]);
    // The state telling us which text box to update
    const [chosenTextBox, setChosenTextBox] = useState(0);

    function modifyValue(index, delta) {
        if (index >= 0 && index < values.length) {
            setValues(values => Object.assign(
                [...values],
                {[index]: values[index] + delta}
            ));
        }
    }    
  
    function setValue(index, value) {
        if (index >= 0 && index < values.length) {
            setValues(values => Object.assign(
                [...values],
                {[index]: value}
            ));
        }
    }    
  
    return (
        <div id="react">
            <div>
                {values.map((value, index) => (
                    <div>
                        Textbox{index + 1}:
                        <input id={index + 1} value={value} onChange={e => setValue(index, +e.target.value)} />
                    </div>
                ))}
            </div>
            <div>
                 <select value={chosenTextBox} onChange={e => setChosenTextBox(+e.target.value)}>
                     {values.map((value, index) => <option value={index}>Textbox{index + 1}</option>)}
                 </select>
                 <button onClick={() => modifyValue(chosenTextBox, 1)}> Increment </button>
                 <button onClick={() => modifyValue(chosenTextBox, -1)}> Decrement </button>
            </div>
        </div>
    )
}

ReactDOM.render(
    <MyApp />,
    document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

Upvotes: 1

Related Questions