Reputation: 678
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
Reputation: 5937
Here is a working codesandbox
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
)
);
};
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