Has anyone found an easy way to implement HeadlessUI and RHF?

All I find are examples with tons of boilerplate and it feels like it shouldn't be as hard to create a form with a custom component made using HeadlessUI or any other headless ui lib.
8 Replies
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
stoyko
stoykoOP2y ago
I'm having issues primarily with the boilerplate that's required, for the component to work properly with RHF. However, I might've found a way to go about it, by using the useController() hook from RHF and reducing most of the boilerplate, by only needing to pass a name for the component and most else is handled internally. No. Issues isn't the correct term. Mostly just don't like the boilerplate. But overall everything works, once you play enough to get it to work.
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
stoyko
stoykoOP2y ago
Just need to get home and I’ll upload a snippet.
stoyko
stoykoOP2y ago
CodeSandbox
solitary-dream-3xkumn - CodeSandbox
solitary-dream-3xkumn using @headlessui/react, @heroicons/react, react, react-dom, react-hook-form, react-scripts, zod
stoyko
stoykoOP2y ago
The combobox component is working and I do think that for the moment, it looks good. Will have to check and see how it fares when validation comes in play, but from what I saw, it works good with zod, so I don't think there will be any problems there.
isaac_way
isaac_way2y ago
@stoyko does that work without passing the control, lol? I always thought you had to pass the control like useController({name, control}) BTW this approach you're taking is the best I've found that's available at the moment for forms in React (using zod resolvers with RHF and having reusable components that take a name as a prop). I've been working on a package that I think I'll have an initial version of up tomorrow some time that handles all of this stuff for you internally while still allowing the usage of custom components. I think it's going to be a lot simpler than anything else out there while being flexible enough to meet any design - The api will look like this:
const mapping = [
[z.string(), TextField],
[z.boolean(), BooleanField],
];
const TSForm = createForm(mapping);

const MyFormSchema = z.object({
name: z.string(),
address: z.string(),
areYouHungry: z.boolean(),
})

function MyComponentWithAForm() {
return (
<TSForm
schema={MyFormSchema}
onSubmit={(data)=>console.log(data)}
/>
)
}
const mapping = [
[z.string(), TextField],
[z.boolean(), BooleanField],
];
const TSForm = createForm(mapping);

const MyFormSchema = z.object({
name: z.string(),
address: z.string(),
areYouHungry: z.boolean(),
})

function MyComponentWithAForm() {
return (
<TSForm
schema={MyFormSchema}
onSubmit={(data)=>console.log(data)}
/>
)
}
React hook form gets used internally, and the schema is used for validation. The control and therefor the error messages etc get passed to the components in the mapping when they're rendered. The idea is that the TSForm component is reusable and you only need to call createForm and create the mapping once per project. The cool thing about the package is that you still have the ability to write 0 markup while also being able to implement any design b/c you can pass typesafe props to the form to have more fine grained control:
<TSForm
schema={MyFormSchema}
onSubmit={(data)=>console.log(data)}
props={{
name: {
variant: 'alternate'
}
}}
/>
<TSForm
schema={MyFormSchema}
onSubmit={(data)=>console.log(data)}
props={{
name: {
variant: 'alternate'
}
}}
/>
This would pass the prop variant={'alternate'} to the TextField component rendered for the name field. Again, totally typesafe, the library knows b/c name is rendered with z.string(), it only accepts TextField props. thoughts?
stoyko
stoykoOP2y ago
For the limited testing I’ve done with it, the above works. But a think a useFormContext would also work. But I will have to play with it more for sure. Also, this sounds interesting and would be great to see how the package turns out.
Want results from more Discord servers?
Add your server