T
TanStack2mo ago
fuzzy-lavender

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
other-emerald
other-emerald2mo ago
what is the structure of that dynamic form?
fuzzy-lavender
fuzzy-lavenderOP2mo 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),
});
other-emerald
other-emerald2mo 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>
fuzzy-lavender
fuzzy-lavenderOP2mo ago
oh so this is the way i will try this and let you know it would be better if this in doc
fuzzy-lavender
fuzzy-lavenderOP2mo 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...
other-emerald
other-emerald2mo ago
also, as const is important for the namespace. See this as example
No description
fuzzy-lavender
fuzzy-lavenderOP2mo 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
other-emerald
other-emerald2mo 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
fuzzy-lavender
fuzzy-lavenderOP2mo 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?