Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to conditionally show/hide fields depending on value of other fields in the form #34

Open
daksh-sagar opened this issue Jan 11, 2023 · 8 comments

Comments

@daksh-sagar
Copy link

let's say i have a checkbox field - billing address is different from shipping address. I want to show additional fields when this checkbox is ticked (with their own set of validations), and hide these fields when the checkbox is not selected.

@iway1
Copy link
Owner

iway1 commented Jan 14, 2023

Right now there's not a simple way to do this with the schema-to-form approach - for these types of situations I think the easiest approach is to use plain JSX right now and build input components that work both with and without react-ts-form.

I do want to solve for this more elegantly as it's a common situation, but I'm not sure what the best solution is quite yet or if a good solution exists. Open to ideas 😃

I think implementing #21 might solve it to some extent? Will need to try it out and see if the DX is good or not.

Ultimately the solution may just be "build components that work both with and without react-ts-form, and if you need to hide certain fields then just use plain JSX with react hook form / zod".

Definitely could use some improved documentation with respect to this as well

@MathisBarre
Copy link

Not stupid but does useTsController work outside the context of react-ts-form ?
If no, it seems complicate to create the same components for both case. Or maybe I'm missing something.

@akd-io
Copy link

akd-io commented Feb 3, 2023

It would be super cool to see a smooth DX for this case. It is the most annoying part of farms in my opinion, and when I found out about react-ts-form, conditional rendering was the first thing I looked for. Might be a hard nut to crack. I for one don't know how one would go about doing it.

Will keep eyes on this thread and let you know if I come up with anything.

@iway1
Copy link
Owner

iway1 commented Feb 7, 2023

@akd-io yeah I'm pretty short on ideas for it honestly other than implementing dependent fields, might be the best we can do with schema based form generation? would love an elegant solution

@iway1
Copy link
Owner

iway1 commented Feb 7, 2023

@MathisBarre currently, useTsController does not work outside of react-ts-form components. It could be possible to make it work outside of them, but IDK if it's a good idea.

With the prop forwarding feature, it's possible to build components that work both with and without react-ts-form:

import {useController} from 'react-hook-form'
function Component({control, name}:{control: Control, name: string}) {
  const {field: {onChange, value}} = useController({control, name});
}

Then to use it outside of react-ts-form but it would also be compatible with react-ts-form because control and name are automatically passed to any components that are rendered via a Form component generated by createTsForm.

The whole idea with prop forwarding was too support these situations - but totally agree building a component for each use case would be bad

@rvetere
Copy link

rvetere commented Feb 14, 2023

I would recommend you to provide a good example in the docs - because this is one main reason why we drop this library now in the evaluation of my company... maybe with good docs, how to write a component to re-use it in both context could help :)

I cannot even access the underlaying "watch" function of react-hook-form to access the state of a single field, just to begin a toggle... I could think of a solution where we push states of a specific field into a context, and then create some complex schemas for the cases where toggling is involved.. then we could access this state from the context and display/hide fields in the complex schema... would this be a solution? Could work in my eyes, but the problem starts that no "watch" is accessible with ts-form... if i need to implement such forms with react-hook-form - then i drop ts-form and zod completely, what saves me about 45kb of bundled code 🤷 This really feels bad as everything else would be AWESOME regarding the DX..

@iway1
Copy link
Owner

iway1 commented Mar 1, 2023

@rvetere watch should be usable, you'll just need to pass in the form prop to the ts-form component:

const form = useForm({resolver: zodResolver(Schema)});
const watch = useWatch({control: form.control});

return <MyForm form={form}/>

Feel free to open an issue if that's causing any issues though.

@scamden
Copy link
Collaborator

scamden commented Apr 19, 2023

FYI conditional show / hide of fields definitely works now with the custom layouts feature of CustomChildComponent added in #66

weirdly useForm didn't work properly for me inside this child (@iway1 thoughts on why? edit: this is because i should RTFM and use useFormContext instead) but useWatch works a treat and is more elegant anyway.

const schema = z.object({
    startDate: z.date(),
    endDate: z.date().nullish(),
    showEndDate: z.boolean(),
  });
  function CustomChildComponent({
    startDate,
    showEndDate,
    endDate,
    ...rest
  }: RenderedFieldMap<typeof schema>) {
    const showEndDateValue = useWatch({ name: 'showEndDate' });
    return (
      <>
        {startDate}
        {showEndDateValue && endDate}
        {showEndDate}
      </>
    );
  }


    <ZodForm schema={schema} onSubmit={() => {}}>
      {CustomChildComponent}
    </ZodForm>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants