Created
April 1, 2024 17:13
-
-
Save bryanltobing/8d2d909e67a823929d15c2e3921042e9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { useForm, FormProvider } from "react-hook-form"; | |
import { zodResolver } from "@hookform/resolvers/zod"; | |
import { z } from "zod"; | |
const baseRincianNilaiSchema = z | |
.object({ | |
name: z.string(), | |
persenan: z.string(), | |
child: z.array(z.any()).optional(), // Fine-tune this as needed | |
}) | |
.deepPartial(); // Make all properties optionally to simplify initial object creation | |
const formSchema = z.object({ | |
parent: z.array(baseRincianNilaiSchema), | |
}); | |
const RecursiveFields = ({ parentPath, methods }) => { | |
const { register, setValue, getValues } = methods; | |
const fieldValue = getValues(parentPath) || []; // Accessing the current value to render existing fields | |
const addChild = (path) => { | |
const newPath = `${path}.child`; | |
const existingChildren = getValues(newPath) || []; | |
setValue(newPath, [ | |
...existingChildren, | |
{ name: "", persenan: "", child: [] }, | |
]); | |
}; | |
return ( | |
<> | |
{fieldValue.map((item, index) => { | |
const currentPath = `${parentPath}[${index}]`; | |
return ( | |
<div key={index} style={{ marginLeft: "20px" }}> | |
<input {...register(`${currentPath}.name`)} placeholder="Name" /> | |
<input | |
{...register(`${currentPath}.persenan`)} | |
placeholder="Persenan" | |
/> | |
<button type="button" onClick={() => addChild(currentPath)}> | |
Add Child | |
</button> | |
{item.child && item.child.length > 0 && ( | |
<RecursiveFields | |
parentPath={`${currentPath}.child`} | |
methods={methods} | |
/> | |
)} | |
</div> | |
); | |
})} | |
</> | |
); | |
}; | |
function App() { | |
const methods = useForm({ | |
resolver: zodResolver(formSchema), | |
defaultValues: { | |
parent: [{ name: "", persenan: "", child: [] }], // Set default values for a minimum of one parent | |
}, | |
}); | |
const addParent = () => { | |
const existingParents = methods.getValues("parent") || []; | |
methods.setValue("parent", [ | |
...existingParents, | |
{ name: "", persenan: "", child: [] }, | |
]); | |
}; | |
return ( | |
<FormProvider {...methods}> | |
{JSON.stringify(methods.watch(), null, 2)} | |
<form onSubmit={methods.handleSubmit((data) => console.log(data))}> | |
<RecursiveFields parentPath="parent" methods={methods} /> | |
<button type="button" onClick={addParent}> | |
Add Parent | |
</button> | |
<input type="submit" /> | |
</form> | |
</FormProvider> | |
); | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment