DEV Community

Aaron K Saunders
Aaron K Saunders

Posted on

1 1

[Video] Using React Hook Form Field Array in a Modal Form

Overview

Create an "Objective" that has subtasks that are required to complete the Objective. Use React Hook Form fields Array functionality to create and Ionic Framework React Components to create a component for a modal form to capture the data.

Alt Text

Whats Covered In The Video

► 1:56 Coding Starts - creating a form with dynamic list items
► 9:38 Passing the form’s data back to parent in a structured object using react hook form
► 13:36 Creating a reusable component, passing properties and calling functions for success in parent component
► 18:07 Going All in with React Hook Form for all input fields
► 21:45 Using Ionic React Components for styling
► 26:24 Deleting Items from the form array
► 27:29 Adding ids to subtasks in the array using an hidden input field
► 29:40 Wrap up

The Video

Source Code

const TaskList: React.FC<any> = ({ onComplete }) => {
const { control, register, handleSubmit, getValues } = useForm();
const { fields, append, remove } = useFieldArray({
control, // control props comes from useForm (optional: if you are using FormContext)
name: "tasks", // unique name for your Field Array
// keyName: "id", default to "id", you can change the key name
});
console.log(getValues());
const doSubmit = (data: any) => {
let returnData = data;
delete returnData["task-input"];
console.log("TASK DATA", returnData);
onComplete(returnData, false);
};
return (
<form onSubmit={handleSubmit(doSubmit)}>
<IonItem style={{ "--padding-start": 0 }}>
<IonLabel>OBJECTIVE NAME</IonLabel>
<Controller
render={({ onChange }) => (
<IonInput type="text" onIonChange={onChange} />
)}
control={control}
defaultValue=""
name="task-title"
/>
</IonItem>
<IonCard>
<IonCardHeader>
<h4>ADD TASKS</h4>
</IonCardHeader>
<IonCardContent>
<IonItem style={{ "--padding-start": 0 }}>
<IonLabel>Sub Task</IonLabel>
<Controller
render={({ onChange }) => (
<IonInput type="text" onIonChange={onChange} />
)}
control={control}
defaultValue=""
name="task-input"
/>
</IonItem>
<IonItem lines="none" style={{ "--padding-start": 0 }}>
<IonButton
onClick={() =>
append({ id: Date.now(), subTask: getValues("task-input") })
}
>
Add Task To Objective
</IonButton>
</IonItem>
</IonCardContent>
</IonCard>
<p>SUB TASKS</p>
{fields.map((task: any, index: number) => {
return (
<IonItem key={task.id} style={{ "--padding-start": 0 }}>
<IonIcon
icon={trashOutline}
onClick={() => remove(index)}
slot="end"
/>
<input
type="hidden"
name={`tasks[${index}].id`}
ref={register()}
defaultValue={task.id}
/>
<Controller
render={({ value, onChange }) => (
<IonInput
type="text"
onIonChange={onChange}
name={`tasks[${index}].subTask`}
ref={register}
value={value}
/>
)}
control={control}
defaultValue={task.subTask} // make sure to set up defaultValue
name={`tasks[${index}].subTask`}
/>
</IonItem>
);
})}
<IonButton type="submit">SAVE IT ALL</IonButton>
<IonButton onClick={() => onComplete(null, true)} color="danger">
CANCEL
</IonButton>
</form>
);
};
view raw TaskList.tsx hosted with ❤ by GitHub

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay