Skip to content

Instantly share code, notes, and snippets.

@bryanltobing
Created April 1, 2024 17:13
Show Gist options
  • Save bryanltobing/8d2d909e67a823929d15c2e3921042e9 to your computer and use it in GitHub Desktop.
Save bryanltobing/8d2d909e67a823929d15c2e3921042e9 to your computer and use it in GitHub Desktop.
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