@hazemazzam/form-controlled
v1.1.0
Published
Generic react-hook-form controlled field wrapper
Maintainers
Readme
@hazemazzam/form-controlled
Lightweight react-hook-form helpers: Controlled wraps Controller with label, error message, and either cloneElement or a render prop for the input.
Install
npm install @hazemazzam/form-controlled react-hook-form react react-domPeers: react, react-dom, react-hook-form (v7+).
Form provider
Form is an alias for FormProvider. Wrap your form:
import { useForm } from "react-hook-form";
import { Form, Controlled } from "@hazemazzam/form-controlled";
const methods = useForm({ defaultValues: { title: "" } });
return (
<Form {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<Controlled name="title" label="Title" children={<input />} />
</form>
</Form>
);cloneElement child (default)
Pass a single React element; value/onChange (or custom prop names) are merged in:
<Controlled name="email" label="Email" children={<input type="email" />} />Render-prop child
Use when the child is not a single element or you need full control:
<Controlled
name="title"
label="Title"
children={(fieldProps) => (
<input
value={fieldProps.value as string}
onChange={(e) => fieldProps.onChange(e)}
onBlur={fieldProps.onBlur as React.FocusEventHandler<HTMLInputElement>}
id={fieldProps.id as string}
name={fieldProps.name as string}
/>
)}
/>Use onChange={(e) => fieldProps.onChange(e)} so the default toFieldValue can read event.target.value. For custom components, call fieldProps.onChange with the value your component emits.
Radix / shadcn-style Switch (checked / onCheckedChange)
Do not use toFieldValue={(x) => Boolean(x)} for stringly values — Boolean("false") is true. Prefer passing real booleans from the Switch, or map explicitly.
<Controlled
name="active"
label="Active"
valueProp="checked"
changeProp="onCheckedChange"
emptyValue={false}
children={<Switch />}
/>Combobox-style (value / onValueChange)
<Controlled
name="country"
label="Country"
valueProp="value"
changeProp="onValueChange"
emptyValue=""
children={<SelectRoot>...</SelectRoot>}
/>forcedValue
When set, the UI shows this value and it is synced into RHF (with shouldValidate: false on sync) so submit uses the forced value.
Exports
Controlled,Form,FormField,FormItem,FormLabel,FormControl,FormDescription,FormMessage,useFormField- Types:
ControlledProps,ControlledPropsRender,ControlledPropsClone,ControlledRenderProps
License
MIT
