#Guidance for Forms for Nested Types

1 messages · Page 1 of 1 (latest)

wise fog
#

Can someone please suggest a good resource for implementing forms for nested types, like for my Basics:

export type Basics = {
  name?: string;
  location?: Location;
  profiles?: Profile[];
};

I have, after many lessons, got some forms working using useActionState and zod-form-data for flat types and I'd like to extend that to nested ones. Gemini has been giving me a bit of a run around for a while, and other guides I've found seem to skirt the issue a bit. My first thought was, why nest vs. just using one form for each type, but having to handle updates to e.g. Location on it's own, then update Basics seems just wrong.

visual skyBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

neon anvil
#

does your form have autosaves or does it need a save button?

#

Nesting would require you to manage states coz you basically are not using the native FormData features.

"use client"

export function BasicsForm(props) {
  
  const [loc, setLoc] = useState(props.location)  
  const [prof, setProf] = useState(props.profiles)
  
  const [state, action, pending] = useActionState(
    async (prev, form) => {
      const name = form.get("name")
      const inputs: Basics = {
         name, locations: loc, profiles: prof
      }  
      const parsed = parseBasicsForm(inputs) // use zod
      const res = await serverActionMutateBasics(parsed)
      return res
    }, null
  )

  return (
    <form action={action}>
      <input name="name" defaultValues={props.name} />
      <LocationInput values={loc} onValueChange={setLoc} />

      <ProfilesInput values={prof} onValueChange={setProf} />    

      <button type="submit">Submit</button>
    </form>
  )
}

#

something like this

neon anvil
#

wdym?

wise fog
#

Haha, sorry, I meant to delete that. I'll try your approach, thanks, merged with what I already have, and see what I can get.

wise fog
#

I'm kind of stubbon, and having got somewhere with the nesting last night, I pushed a bit more and got something right. I'm doing this:

...
                    <HtmlTextField name={"dateOfBirth"} required={true} formState={state} />
                    <HtmlTextField name={"nationality"} required={true} formState={state} />
                    <HtmlTextField name={"workAuth"} required={true} label={"Work Authorization"} formState={state} />
                    <HtmlTextField name={"location.address"} required={true} label={"Address"} formState={state} />
                    <HtmlTextField name={"location.city"} required={true} label={"City"} formState={state} />
                    <HtmlTextField name={"location.postalCode"} required={true} label={"Postal Code"} formState={state} />
...

and this:

export async function updateBasics(
  prevState: EditBasicsFormState,
  formData: FormData,
): Promise<EditBasicsFormState> {
  const preprocessor = zfd.formData(basicsSchema);
  const result = preprocessor.safeParse(formData);
  console.log(util.inspect(result, { depth: null }));

  const values = Object.fromEntries(
    formData,
  ) as unknown as EditBasicsFormState["values"];

and the log output here has all the wanted data, as well as the log out output on the route that hosts the form component.

neon anvil
#

Nice