Hema Nandagopal
Hema Nandagopal

Reputation: 678

Creating dynamic checkboxs for each row using react js

I've rows with two inputs in a form when clicked on add, it will add new row. So, from the second row, on clicking add it should add checkbox 1 to show that the second row is dependent on first and for the third row it should create 2 checkboxes saying checkbox 1 checkbox 2.When the save button is clicked it should be saved with its rows inputs corresponding checkbox clicked.

I'm able to create dynamic checkboxes for each row but unable to send value selected checkbox value for each row. The e.target.value is showing as 1 ,2,3, when I click the check box but its not appending to the "dependent" as "dependent":"1,2,3"

https://codesandbox.io/s/practical-stallman-msr7n?file=/src/App.js

Upvotes: 2

Views: 873

Answers (1)

Sinan Yaman
Sinan Yaman

Reputation: 5937

Here is a working codesandbox

Explanation

When you try to update the state like this:

let copyState = [...prevState]; // creates a shallow copy
copyState[index][key] = value;
if (value === "toggle")
   copyState[index][key] = !copyState[index][key]; // mutates state, doesn't change

Instead, you should replace the whole state with a new one. Importing lodash and calling copyState = lodash.deepCopy(prevState) will help. But my suggestion is:

  const onChangeFieldValue = (index, key, value) => {
    setFormValues((prevState) =>
      prevState.map((el, idx) => //Map function creates an entirely new array
        idx === index
          ? value === "toggle"
            ? { ...el, [key]: !el[key] }
            : { ...el, [key]: value }
          : el
      )
    );
  };

Snippet

const { useState, Fragment } = React;

const App = () => {
  const [formValues, setFormValues] = useState([
    { orderno: 1, inputValue1: "", inputValue2: "", checked: false }
  ]);

  // control order number in a state to make sure
  // that it does not get messed when you remove
  // an indice from formValues
  // !! default was 0. so set it to 1
  const [orderNumber, setOrderNumber] = useState(1);

  const addFormFields = () => {
    setFormValues((prevState) => [
      ...prevState,
      {
        orderno: orderNumber + 1,
        inputValue1: "",
        inputValue2: "",
        checked: false
      }
    ]);
    // increment order number
    setOrderNumber((prev) => prev + 1);
  };

  const removeFormFields = (i) => {
    let newFormValues = [...formValues];
    newFormValues.splice(i, 1);

    setFormValues(newFormValues);

    // decrement order number
    setOrderNumber((prev) => prev - 1);
  };

  const onChangeFieldValue = (index, key, value) => {
    setFormValues((prevState) =>
      prevState.map((el, idx) =>
        idx === index
          ? value === "toggle"
            ? { ...el, [key]: !el[key] }
            : { ...el, [key]: value }
          : el
      )
    );
  };

  const saveFields = (e) => {
    const queryparam = {
      data: "xxx",
      DbData: "xxx",
      SQlData: "xxx", // only checked ones
      overallData: { formValues }
    };
    console.log(queryparam, "hhhhhhh");
    //axios.post('..',queryparam)
  };
  return <Fragment>
      {formValues.length <= 4 ? formValues.map((element, index) => (
            <div className="form-inline" key={index}>
              <label>{index + 1}</label>

              <input
                type="text"
                value={element.inputVal1}
                onChange={(e) =>
                  onChangeFieldValue(index, "inputValue1", e.target.value)
                }
              />
              <input
                type="text"
                value={element.inputVal2}
                onChange={(e) =>
                  onChangeFieldValue(index, "inputValue2", e.target.value)
                }
              />
              <input
                type="checkbox"
                checked={element.checked}
                onChange={(e) => onChangeFieldValue(index, "checked", "toggle")}
              />
              <button
                className="button add"
                type="button"
                onClick={() => addFormFields()}>
                Add
              </button>

              <button
                type="button"
                className="button remove"
                onClick={() => removeFormFields(index)}>
                Remove
              </button>
            </div>
          ))
        : ""}
      <button
        type="button"
        className="button remove"
        onClick={(e) => saveFields(e)}>
        Save
      </button>
      <button
        type="button"
        className="button remove">
        cancel
      </button>
    </Fragment>
};

ReactDOM.render(<App />, document.getElementById('react'))
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

Upvotes: 3

Related Questions