T
TanStack5mo ago
automatic-azure

How can we pass from object and it's type to child ?

i have to dynamiclly generate from based on user input so i need to pass from object currently i m doing from:any which works but reactive is not working
{allVariants?.map((variant, index) => {
<VariantForm
key={`variant-form-${index}-${variantKey}`}
variant={variant}
index={index}
from={from}
/>
}}
{allVariants?.map((variant, index) => {
<VariantForm
key={`variant-form-${index}-${variantKey}`}
variant={variant}
index={index}
from={from}
/>
}}
thanks please help me
9 Replies
harsh-harlequin
harsh-harlequin5mo ago
what is the structure of that dynamic form?
automatic-azure
automatic-azureOP5mo ago
const productVariantsSchema = z.object({
slug: z.string().min(1),
name: z.string().min(1),
sku: z.string().min(1),
price: z.number().min(1, 'Please enter price'),
stock: z.number().min(1, 'Please enter stock'),
images: z.array(z.string()).min(1, "At least one image is required"),
discountType: discountTypeEnum.optional(),
discountValue: z.number().optional(),
is_default: z.boolean().optional().transform(x => {
if (x) {
return true;
} else {
return false;
}
}),
variantIds: z.string().optional()
});

const productSchema = z.object({
name: z.string().min(2),
description: z.string().min(3),
categoryId: z.number().int().positive(),
productVariants: z.array(productVariantsSchema),
});
const productVariantsSchema = z.object({
slug: z.string().min(1),
name: z.string().min(1),
sku: z.string().min(1),
price: z.number().min(1, 'Please enter price'),
stock: z.number().min(1, 'Please enter stock'),
images: z.array(z.string()).min(1, "At least one image is required"),
discountType: discountTypeEnum.optional(),
discountValue: z.number().optional(),
is_default: z.boolean().optional().transform(x => {
if (x) {
return true;
} else {
return false;
}
}),
variantIds: z.string().optional()
});

const productSchema = z.object({
name: z.string().min(2),
description: z.string().min(3),
categoryId: z.number().int().positive(),
productVariants: z.array(productVariantsSchema),
});
harsh-harlequin
harsh-harlequin5mo ago
so you have a big form that has productsVariantsSchema as its structure. You want to split off parts of the form (the variant) and generate it once per item in the array. The way to do that would be using withForm in Form Composition You would have a structure like:
const defaultValues: z.input<typeof productSchema> = { /* ... */ };
// These are common options across your forms
const sharedFormOptions = formOptions({
defaultValues,
validators: {
onChange: productSchema
}
})

// variant-form.tsx
const VariantForm = withForm({
...sharedFormOptions,
// when calling VariantForm, you must pass the index
props: {
index: 0
},
render: function Render({ form, index }) {
// your form fields are located here
const namespace = `productVariants[${index}]` as const;
return <form.AppField name={`${namespace}.slug`} /* ... */ />
}
})

// main.tsx
const form = useAppForm({
...sharedFormOptions,
// if your defaultValues are async, overwrite them here
defaultValues: fromQuery.data,
onSubmit: ({ value }) => { /* ... */ }
})

// iterate over variants
<form.AppField name="productVariants" mode="array">
{field => field.state.value.map((variant, index) => <VariantForm form={form} index={index} />)
</form.AppField>
const defaultValues: z.input<typeof productSchema> = { /* ... */ };
// These are common options across your forms
const sharedFormOptions = formOptions({
defaultValues,
validators: {
onChange: productSchema
}
})

// variant-form.tsx
const VariantForm = withForm({
...sharedFormOptions,
// when calling VariantForm, you must pass the index
props: {
index: 0
},
render: function Render({ form, index }) {
// your form fields are located here
const namespace = `productVariants[${index}]` as const;
return <form.AppField name={`${namespace}.slug`} /* ... */ />
}
})

// main.tsx
const form = useAppForm({
...sharedFormOptions,
// if your defaultValues are async, overwrite them here
defaultValues: fromQuery.data,
onSubmit: ({ value }) => { /* ... */ }
})

// iterate over variants
<form.AppField name="productVariants" mode="array">
{field => field.state.value.map((variant, index) => <VariantForm form={form} index={index} />)
</form.AppField>
automatic-azure
automatic-azureOP5mo ago
oh so this is the way i will try this and let you know it would be better if this in doc
automatic-azure
automatic-azureOP5mo ago
Form Composition | TanStack Form React Docs
A common criticism of TanStack Form is its verbosity out-of-the-box. While this can be useful for educational purposes helping enforce understanding our APIs it's not ideal in production use cases. As...
harsh-harlequin
harsh-harlequin5mo ago
also, as const is important for the namespace. See this as example
No description
automatic-azure
automatic-azureOP5mo ago
okay let me try this can we pass sharedFormOptions(isEdit) as i m doing same form for edit and create and pass default values
harsh-harlequin
harsh-harlequin5mo ago
withForm expects exactly the same form grouping fields for multiple forms is not implemented yet. There is a PR ready, but it is not released yet
automatic-azure
automatic-azureOP5mo ago
oh okay thanks i will check this later becouse now react-hook-from does the job for now

Did you find this page helpful?