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.
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> | |
); | |
}; |
Top comments (0)