T
TanStack7mo ago
harsh-harlequin

Is there a way to create subforms?

I would love a way to create a group of fields that always look the same, but I can nest them under a object or similar and reuse the same component This doesn't work and I cannot find a way to do this right now. Is this already possible? I would love a way to do this with type safety, as I find this comes up quite often. A way to add a prefix or a subform would solve this really well I think
2 Replies
harsh-harlequin
harsh-harlequinOP7mo ago
An example:
const addressSchema = z.object({
addressLine: z.string(),
state: z.string(),
});

const AddressForm = withForm({
validators: {
onSubmit: addressSchema,
},
defaultValues: {
addressLine: "",
state: "",
},
props: {
title: "Address",
},
render: ({ form, title }) => {
return (
<div>
<p>{title}</p>
<form.AppField name="addressLine">
{(field) => <field.TextField label="First Name" />}
</form.AppField>
<form.AppField name="state">
{(field) => <field.TextField label="Last Name" />}
</form.AppField>
</div>
);
},
});

function App() {
const form = useAppForm({
defaultValues: {
address: {
addressLine: "",
state: "",
},
billingAddress: {
addressLine: "",
state: "",
},
},
onSubmit: ({ value, formApi }) => {
console.log(value);
formApi.reset();
},
});

return (
<div className="text-center">
<form
action={() => {
form.handleSubmit();
}}
>
<form.Field name="address">
{(field) => <AddressForm title="Address" form={field.form} />}
</form.Field>

<form.Field name="billingAddress">
{(field) => <AddressForm title="Billing Address" form={field.form} />}
</form.Field>
</form>
</div>
);
}
const addressSchema = z.object({
addressLine: z.string(),
state: z.string(),
});

const AddressForm = withForm({
validators: {
onSubmit: addressSchema,
},
defaultValues: {
addressLine: "",
state: "",
},
props: {
title: "Address",
},
render: ({ form, title }) => {
return (
<div>
<p>{title}</p>
<form.AppField name="addressLine">
{(field) => <field.TextField label="First Name" />}
</form.AppField>
<form.AppField name="state">
{(field) => <field.TextField label="Last Name" />}
</form.AppField>
</div>
);
},
});

function App() {
const form = useAppForm({
defaultValues: {
address: {
addressLine: "",
state: "",
},
billingAddress: {
addressLine: "",
state: "",
},
},
onSubmit: ({ value, formApi }) => {
console.log(value);
formApi.reset();
},
});

return (
<div className="text-center">
<form
action={() => {
form.handleSubmit();
}}
>
<form.Field name="address">
{(field) => <AddressForm title="Address" form={field.form} />}
</form.Field>

<form.Field name="billingAddress">
{(field) => <AddressForm title="Billing Address" form={field.form} />}
</form.Field>
</form>
</div>
);
}
absent-sapphire
absent-sapphire7mo ago
GitHub
Compose forms with nested form structure · TanStack form · Discussi...
The new createFormHook looks great but it appears that it only works when there's a shared data structure between the child and parent forms. The use case where this applies is when you have a ...

Did you find this page helpful?