Hello everyone I tried getting react-hook-form to work with KotlinJS using Dukat and Wrappers, this is what I got.
(the wrapper works fine, tried logging it in the console and it indeed is useForm from the library)
This is how I try to use the useForm hook
val useForm = useForm<ProfileModel>()
val register = useForm.register
val errors = useForm.formState.errors
val handleSubmit = useForm.handleSubmit
val registerInstagram = register("instagram", object : validateOptions<ProfileModel, Any> {
override var required = true
override var maxLength = 40
})
form(classes = "") {
attrs.onSubmit = {
it.preventDefault()
console.log("Submit")
handleSubmit({ data, ev ->
console.log("On Submit " + data)
}, { errors, ev ->
console.log("On submit error " + errors)
})
}
input(type = InputType.text,
classes = "$defaultInputStyle mb-4") {
attrs.placeholder = "Name"
register("name", object : validateOptions<ProfileModel, Any> {
override var required = true
override var maxLength = 15
})
}
input(type = InputType.text,
classes = "$defaultInputStyle mb-4") {
this.ref = registerInstagram.ref
attrs {
this.placeholder = "Instagram"
this.onChange = registerInstagram.onChange
this.onBlur = registerInstagram.onBlur
this.name = registerInstagram.name
}
}
button(classes = defaultButtonStyle, type = ButtonType.submit) {
+"Submit"
}
}
}
useForm indeed does work and it gives me all of the right values like register, errors and such but I am unable to properly connect it to the Input element in Kotlinjs.
Register returns the following, I edited the interface to fit into the attributes of React DOM, as in regular react form hook you'd use <Input (...register) which would just apply all of these 4 things to the element.
external interface UseFormRegisterReturn {
var onChange: ChangeEventHandler<*> // I changed this
var onBlur: FocusEventHandler<*> // I changed this
var ref: RefCallback<*> //I changed this
var name: InternalFieldName
}
When I click submit I get the submit printed but the handleSubmit from the useForm isn't ran and no data is getting printed. Not sure what else can I do with this setup.
Here's the rest of the relevant Wrapper code
@JsName("useForm")
external fun <TFieldValues : FieldValues> useForm(props: `T$23`<TFieldValues> = definedExternally): UseFormReturn<TFieldValues, Any>
external interface UseFormReturn<TFieldValues : FieldValues, TContext : Any?> {
var watch: UseFormWatch<TFieldValues>
var getValues: UseFormGetValues<TFieldValues>
var setError: UseFormSetError<TFieldValues>
var clearErrors: UseFormClearErrors<TFieldValues>
var setValue: UseFormSetValue<TFieldValues>
var trigger: UseFormTrigger<TFieldValues>
var formState: FormState<TFieldValues>
var reset: UseFormReset<TFieldValues>
var handleSubmit: UseFormHandleSubmit<TFieldValues>
var unregister: UseFormUnregister<TFieldValues>
var control: Control<TFieldValues, TContext>
var register: UseFormRegister<TFieldValues>
var setFocus: UseFormSetFocus<TFieldValues>
}
Basically, I am wondering how can I register the useForm to my elements.
EDIT: Some things you have to do
div("w-screen h-screen items-center justify-center p-4") {
form(classes = "") {
attrs.onSubmit = {
it.preventDefault() 1)
handleSubmit({ data, ev ->
console.log("On Submit ", data)
}, { errors, ev ->
console.log("On submit error ", errors)
})(it) 2)
}
input(type = InputType.text,
classes = "$defaultInputStyle mb-4") {
this.ref = registerInstagram.ref
attrs { 3)
this.placeholder = "Instagram"
this.onChange = registerInstagram.onChange
this.onBlur = registerInstagram.onBlur
this.name = registerInstagram.name
}
}
button(classes = defaultButtonStyle, type = ButtonType.submit) {
+"Submit"
}
- Prevent default (if you don't want page refresh)
- the function handleSubmit RETURNS A FUNCTION that needs an event as its parameter. This was missing for me, you need to call the handleSubmit()()
- Apply all of the stuff returned from the register function, onBlur, name onChange and ref
This at least sends the data, but validation and errors aren't still happening