Home > other >  Handle multiple inputs with one onChange function handler
Handle multiple inputs with one onChange function handler

Time:07-02

i have a scenario where based on a number(tenure) i want to render tenure times an input field of date type. how to get values of all inputs when they change?[these are the number of inputs based on tenure]

CodePudding user response:

Presented below is one possible way to achieve the desired objective.

Code Snippet

const {useState, useEffect} = React;
const Thingy = ({...props}) => {
  // state to hold tenure (number) input from user
  const [tenure, setTenure] = useState(null);
  // state to hold tenure-dates (array of varying size)
  const [tnDates, setTnDates] = useState(null);

  // update tenure when user input changes
  const handleTenureChange = ev => setTenure(ev.target.value);
  
  // when 'tenure' gets updated, update the tenure-dates array
  useEffect(() => setTnDates(
    (tenure && tenure > 0)
      ? ( [...Array( tenure).keys()].map(
        id => ({id, tenureDate: ''})
      )) : null
  ), [tenure]);
  
  // when user inputs a particular date, accept the input 
  // and update the specific element in the array
  const handleDateChange = ev => {
    const idx = ev.target.id;       // to access specific array element
    const val = ev.target.value;    // to access the date-value selected by user
    setTnDates(prev => {            // "prev" is the current array
      const nd = [...prev];         // shallow-copy "prev" into "nd" (new-data) array
      nd[idx].tenureDate = val;     // update the "tenureDate" at position "idx"
      return nd;                    // return the updated "nd" array to store into state
    });
  };

  return (
    <div>
      <label>Tenure: </label>
      <input type='number' value={tenure}
        onChange={handleTenureChange}
      />
      {tenure && tenure > 0 && (<div style={{ margin: '10px 0' }}>
        Select dates
        <div
          style={{
            display: 'flex', flexDirection: 'column',
            width: '45%', marginTop: '10px'
          }}
        >{tnDates &&
          Array.isArray(tnDates) &&
          tnDates.length > 0 &&
          tnDates.map(
            ({id, tenureDate}) => (
              <input
                style={{ margin: '5px 0'}}
                key={id} id={id} type="date"
                value={tenureDate}
                onChange={handleDateChange}
              />
            )
        )}</div>
        <div style={{ marginTop: '10px' }}>
          Place buttons for futher processing here...
        </div>
      </div>)}
    </div>
  );
};

ReactDOM.render(
  <div>
    <h3>DEMO</h3>
    <Thingy />
  </div>,
  document.getElementById("rd")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="rd" />

Explanation

Inline comments added to the snippet above.

CodePudding user response:

You can add an input element for tenure, then add input field for taking dates dynamically. For each date input you can bind 'change' event on which you can collect values of all dates. Finally add those dynamically created inputs in div with id 'container'

For e.g

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <input type="number" onchange="tenureChange(this.value)" />
    <div id="container"></div>

    <script type="text/javascript">
      function tenureChange(value) {
        let n = value || 0;
        n = parseInt(n);

        let inputsArray = [];
        for (let i = 0; i < n; i  ) {
          const input = document.createElement("input");
          input.type = "date";
          input.classList.add("date-input");
          input.addEventListener("change", () => {
            const inputs = document.querySelectorAll(".date-input");
            inputs.forEach((input) => console.log(input.value));
          });
          inputsArray.push(input);
        }
        document.getElementById("container").replaceChildren(...inputsArray);
      }
    </script>
  </body>
</html>
  • Related