This component will generate a form template you can use to generate form fields with an object:
To add a single field in the exisiting form useState Object. The example below calls the first property object.
To call dyanmically to a new field that is not in the useState object and a new field:
import { useState } from "react";
function Math() {
const handleSubmit = (e) => {
e.preventDefault();
// console.log(`LINE 73 e=`, e);
//console.log(`LINE 73 form=`, form);
const postData = {};
for (let [fieldName, field] of Object.entries(form)){
//console.log(`LINE 73a fieldName=`, fieldName);
postData[field.name] = field.value;
}
console.log(`LINE 73b postData=`, postData);
// SEND VIA AXIOS
}
const [form, setForm] = useState(
{
myselect: { type: "select", title: "My Select", name: "select", dataValues: [{ '+': 'Addition' }, { '-': 'Substraction' }, { '*': 'Multiplication' }, { '/': 'Dvision' }], value: '+' },
mytextarea: { type: "textarea", title: "Textarea Box", name: "name", value: "This is the text area default value" },
myradio: { type: "radio", title: "Radios", name: "radio", dataValues: ['one', 'two', 'three'], value: "" },
mycheckbox: { type: "checkbox", title: "CheckBoxes", name: "checkbox", checked: false, value: "agree" },
mytext: { type: "text", title: "Your Name", name: "name", value: "John", className: "form-control" },
myemail: { type: "email", title: "Email", name: "email", value: "[email protected]", className: "form-control" },
mypassword: { type: "password", title: "Password", name: "password", value: "pass124", className: "form-control" }, //onChange: 'handleAction'
mysubmit: { type: "submit", title: "Submit", name: "submit", value: "Submit", className: "btn btn-primary" }, //onChange: 'handleAction'
}
);
const updateRadio = (fieldName, index, value) => {
const new_form = { ...form }; // copy the array
if (new_form[fieldName].type == 'radio') {
new_form[fieldName]['dataValues'][index] = value;
new_form[fieldName]['value'] = value;
} else if (new_form[fieldName].type == 'checkbox') {
new_form[fieldName]['checked'] = !new_form[fieldName]['checked']; // toggle checkbox
} else if (new_form[fieldName].type == 'select') {
} else {
// input:text,password...
new_form[fieldName]['value'] = value;
}
setForm(new_form); // return a new data object
}
const generateField = (field, fieldName) => {
switch (field.type) {
case 'textarea':
return <textarea
defaultValue={form[fieldName].value}
className="form-control"
// rows={4}
// cols={40}
name={form[fieldName].name}
onChange={(e) => setForm(
{
...form, [fieldName]: {
...form[fieldName],
value: e.target.value
}
})}
></textarea>
break;
case 'checkbox':
return (<div className="form-check">
<input
className="form-check-input"
type="checkbox"
id={`${fieldName}`}
name={form[fieldName].name}
value={form[fieldName].value}
onChange={(e) => updateRadio(fieldName, '', e.target.value)}
/>
<label className="form-check-label" htmlFor={`${fieldName}`}>
{form[fieldName].value} | {form[fieldName].checked}
</label>
</div>
)
break;
case 'radio':
return (
<>
{form[fieldName].dataValues.map((value, index) => {
return (
<div className={`form-${field.type}`} key={index}>
<input
type={field.type}
id={`${fieldName}`}
className="form-check-input"
name={form[fieldName].name}
value={value}
onChange={(e) => updateRadio(fieldName, index, e.target.value)}
/>
<label className="form-check-label" htmlFor={`${fieldName}`}>
{value} | {index}
</label>
</div>
)
})}
</>
)
case 'select':
return (
<select
name={form[fieldName].name}
id={`${field.name}`}
className="form-select"
aria-label="Default select example"
onChange={(e) => updateRadio(fieldName, '', e.target.value)}
defaultValue={form[fieldName].value}
>
{form[fieldName].dataValues.map((value, index) => <option
key={index}
value={Object.keys(value)[0]}
>{value[Object.keys(value)[0]]}</option>)}
</select>
)
break;
default: return <input
{...form[fieldName]}
onChange={(e) => updateRadio(fieldName, '', e.target.value)}
/>
break;
}
}
return (
<>
<div className="container">
<div className="row">
<form onSubmit={handleSubmit}>
{Object.entries(form).map(([fieldName, field], index) => {
return (
<div className="mb-3" key={index}>
{/* <pre>{JSON.stringify(field, null, 2)}</pre> */}
<label htmlFor={fieldName} className="form-label">{field.title}</label>
{generateField(field, fieldName)}
{field.description && <div className="form-text">{field.description}</div>}
</div>
)
})}
</form>
</div>
</div>
</>
)
}
export default Math