Skip to content

Instantly share code, notes, and snippets.

@saiashirwad
Created January 27, 2024 18:03
Show Gist options
  • Save saiashirwad/2b06c954d99237407079c3ddf7c844b7 to your computer and use it in GitHub Desktop.
Save saiashirwad/2b06c954d99237407079c3ddf7c844b7 to your computer and use it in GitHub Desktop.
controllable-fields
type ControlledField<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
control: Control<TFieldValues>;
name: TName;
label?: string;
description?: string;
render: (props: {
field: ControllerRenderProps<TFieldValues, TName>;
fieldState: ControllerFieldState;
formState: UseFormStateReturn<TFieldValues>;
}) => ReactNode;
};
type ControlledFieldProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
control: Control<TFieldValues>;
name: TName;
label?: string;
description?: string;
required?: boolean;
render: (props: {
field: ControllerRenderProps<TFieldValues, TName>;
fieldState: ControllerFieldState;
formState: UseFormStateReturn<TFieldValues>;
}) => ReactNode;
};
export function ControlledField<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(props: ControlledFieldProps<TFieldValues, TName>) {
return (
<FormField
control={props.control}
name={props.name}
render={(render) => (
<FormItem>
<FormLabel>
{props.label}
{props.required && <span className='pl-1 text-destructive'>*</span>}
</FormLabel>
<FormControl>
{props.render({
field: render.field,
fieldState: render.fieldState,
formState: render.formState,
})}
</FormControl>
<FormDescription>{props.description}</FormDescription>
<FormMessage />
</FormItem>
)}
/>
);
}
export function InputField<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
props: Omit<ControlledFieldProps<TFieldValues, TName>, 'render'> & InputProps,
) {
return (
<ControlledField
{...props}
render={({ field, formState, fieldState }) => (
<Input {...field} {...props} />
)}
/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment