-
-
Notifications
You must be signed in to change notification settings - Fork 14
Description
The second approach would be what you already did but with a modified version of the
ValidPathtype that let's you specify a datatype so that e.g. only paths to string fields can be specified.We could also start an issue to discuss whether our field hook and component should provide a connected version of our
setInputmethod where you directly can pass over the new value without specifying the form and path.
Originally posted by @fabian-hiller in #32
The ability to mutate a field without a reference to the form would allow me to use less code, and a more convenient API when building complex input components.
I have some thoughts on how this should work
A form is a field
I'll explain by example: I have a "user form" for getting the user data I need.
const AddressSchema = v.object({
street: v.string(),
city: v.string(),
state: v.string(),
zip: v.string()
})
const UserSchema = v.object({
firstName: v.string(),
lastName: v.string(),
address: AddressSchema
})
Somewhere else, I need a form for just the address. So I create an "address form" component. The "user form" can now just use the address form, within it. This is an example of how a form can be a field, and something I keep encountering in my usage.
From another perspective, consider how a form is based on a valibot schema. In valibot, UserSchema is a schema, and AddressSchema is a schema. But on my user form, the UserSchema becomes the form, which is treated one way, and AddressSchema becomes a field, which is treated differently.
setInput
I would prefer an API like this
// No changes
const form = createForm({ schema: UserSchema })
const address = useField(form, { path: ["address"] })
// Current API still works
setInput(form, {
path: ["firstName"],
input: "John"
})
// Changes below
// Set input of field (without path)
setInput(address, {
input: {
street: "123 Main St",
city: "Anytown",
state: "CA",
zip: "12345"
}
})
// Set input of field (with path)
setInput(address, {
path: ["street"],
input: "456 Oak Ave"
})useFieldArray (and FieldArray)
This primitive requires a path, so when I want to use it on an array schema I must wrap it in an object. This goes against my "a form is a field" ideal. Perhaps there are other areas where paths should not be required.
Advantages
The largest practical advantage for me, is that when I'm building and using components (#32), I only care about the field store. The form it is a part of and the path in that form are of no concern in the component (the component probably wouldn't be reusable if it were).
When using my component, I can just pass the field
{/* Current API */}
<AddressField of={form} path={["address"]} />
{/* Preferred API */}
<Field of={form} path={["address"]}>
{(field) => <AddressField field={field} />}
</Field>This makes typing simple, and also works when the form was created with the AddressSchema.
{/* Just need to pass the form */}
<AddressField field={form} />