We need to plot a form whose entire fields are coming from the backend. Since the fields are not known in advance, we cannot add them statically. The data about each field, such as its id to save with, name, validations, etc. all comes in the API response too.
For the given scenario, I have used React Hook Form. The demo and example code for a dynamic questionnaire is shared below.
Demo
Example Code
import React, { useState } from "react";
import { useForm, useFieldArray } from "react-hook-form";
export default function DynamicForm() {
const {
control,
register,
handleSubmit,
watch,
formState: { errors }
} = useForm();
const [loading, setLoading] = useState(false);
const { fields, append } = useFieldArray({
control,
name: "questionnaire"
});
const value = watch("questionnaire");
const questionnaireFromBackend = [
{
id: 1,
value: "",
placeholder: "First Name",
required: true
},
{
id: 2,
value: "",
placeholder: "Middle Name"
},
{
id: 3,
value: "",
placeholder: "Last Name",
required: true
}
];
const loadQuestionnaire = () => {
setLoading(true);
setTimeout(() => {
setLoading(false);
questionnaireFromBackend.forEach((q) => {
append(q, { shouldFocus: false });
});
}, 3000);
}
const onSubmit = (data) => {
console.log(data);
// submit dynamic questionnaire!
};
return (
<div
style={{
borderStyle: "ridge",
padding: "10px",
minHeight: "300px"
}}>
{
(!loading && !fields.length)
&&
<button
type="button"
onClick={loadQuestionnaire}>
Load Questionnaire
</button>
}
{loading ? (
"loading questionnaire..."
) : (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
{fields.map((field, index) => (
<div key={field.id} style={{ marginBottom: "10px" }}>
<input
{...register(`questionnaire.${index}.value`, {
required: value[index].required
})}
placeholder={value[index].placeholder}
/>
<br></br>
{errors?.questionnaire?.[index] && (
<span style={{ color: "red", fontSize: "small" }}>
{value[index].placeholder} is required
</span>
)}
</div>
))}
</div>
<br></br>
{!loading && fields.length > 0 && <input type="submit" />}
</form>
)}
</div>
)
}
In this next post I’m going to share how to handle dynamic conditional fields in a form.
See also
- SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
- Yup Date Format Validation With Moment JS
- Yup Number Validation: Allow Empty String
- Exactly Same Query Behaving Differently in Mongo Client and Mongoose
- JavaScript Unit Testing JSON Schema Validation
- Reduce JS Size With Constant Strings
- JavaScript SDK