New Features
Support for nested data by using paths for field names.
Thanks @lucascurti! #4
Example form:
export default function MyForm() {
const { defaultValues } = useLoaderData();
return (
<ValidatedForm
validator={validator}
method="post"
defaultValues={defaultValues}
>
<MyInput name="firstName" label="First Name" />
<MyInput name="lastName" label="Last Name" />
<MyInput name="address.street" label="Street" />
<MyInput name="address.city" label="City" />
<MyInput name="phones[0].type" label="Phone 1 Type" />
<MyInput name="phones[0].number" label="Phone 1 Number" />
<MyInput name="phones[1].type" label="Phone 2 Type" />
<MyInput name="phones[1].number" label="Phone 2 Number" />
<MySubmitButton />
</ValidatedForm>
);
}
When you validate in your action, the data for this form will come out like this:
{
firstName: 'John',
lastName: 'Doe',
address: {
street: 'Some street',
city: 'Anytown',
},
phones: [
{ number: '5551234', type: 'cell' },
{ number: '5552345', type: 'home' },
],
}
And when you pass defaultValues
to the ValidatedForm
, this is the shape it will expect for those.
Validators can accept FormData
directly
A small DX improvement, you no longer need to use Object.fromEntries
to convert your FormData
before validating it.
You can still pass plain objects to the validator as well.
- const data = validator.validate(Object.fromEntries(await request.formData()));
+ const data = validator.validate(await request.formData());
Breaking changes
This change is only breaking if you have fields in your forms that contain dots .
or square brackets []
.
There isn't currently a way to escape these characters and create fields with names that contain these characters.
If this feature is important to you, please feel free to file an issue. 😄
Migrating
If you already have a form fields that have paths for names (my.field[0]
), you will need to update the following:
- You validation schemas should expect a nested data structure rather than an object with paths for keys.
- Any code consuming the return value of a validator should also expect a nested data structure.
- When passing
defaultValues
to a form, it expects a nested data structure.
- const validator = withYup(yup.object({
- "nested.field": yup.string().required(),
- "arrayField[0]": yup.string().required(),
- })
+ const validator = withYup(yup.object({
+ nested: yup.object({ field: yup.string().required() })
+ arrayField: yup.array(yup.string())
+ })
// Expected return value from `validator.validate`
- {
- "nested.field": "some value",
- "arrayField[0]": "another value",
- }
+ {
+ nested: { field: "some value" }
+ arrayField: ["another value"]
+ }