2

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

2
  • can you please explain more about your expectation? the current explanation is not clear. Commented Oct 26, 2021 at 10:20
  • also, add the related parts of the snippet into question, I know that you added a codesandbox, but it's better to include the essential related parts within your question. Commented Oct 26, 2021 at 10:22

1 Answer 1

3

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>

Sign up to request clarification or add additional context in comments.

2 Comments

Its not adding two checkboxes for 3rd row and 3 checkboxes for the fourth row which is the Maximum number of rows which can be added.
can you please check the updated question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.