T
TanStack4mo ago
correct-apricot

Multiple reusable fields in one component

Hey, I'm just learning the API and have a question about composition. I want to create a component that contains multiple fields and is reusable across mutiple forms. For that i created a defaultValue setting with just the used fields in the component:
import TextField from "@/components/form/fields/TextField";
import { withForm } from "@/components/form/hooks/form";
import { FC } from "react";
import { NatsSubjectInput } from "@/dtos/testingclient";
export const SubjectField = withForm({
defaultValues: {
subject: {
fromString: "",
parseAsTemplate: true,
} as NatsSubjectInput,
},
render: function Render({ form }) {
return (
<>
<form.AppField
name="subject.fromString"
children={(field) => (
<>
<field.TextField label="Subject" placeholder="orders" />
</>
)}
/>
<form.AppField
name="subject.parseAsTemplate"
children={(field) => (
<field.CheckboxField label="Parse as template" />
)}
/>
</>
);
},
});
import TextField from "@/components/form/fields/TextField";
import { withForm } from "@/components/form/hooks/form";
import { FC } from "react";
import { NatsSubjectInput } from "@/dtos/testingclient";
export const SubjectField = withForm({
defaultValues: {
subject: {
fromString: "",
parseAsTemplate: true,
} as NatsSubjectInput,
},
render: function Render({ form }) {
return (
<>
<form.AppField
name="subject.fromString"
children={(field) => (
<>
<field.TextField label="Subject" placeholder="orders" />
</>
)}
/>
<form.AppField
name="subject.parseAsTemplate"
children={(field) => (
<field.CheckboxField label="Parse as template" />
)}
/>
</>
);
},
});
Now when i use the component in the main form component (which has these fields and many more), it complains that the form input isn't correct:
Type '{ subject: NatsSubjectInput; }' is missing the following properties from type 'PublishSpec': count, body
Type '{ subject: NatsSubjectInput; }' is missing the following properties from type 'PublishSpec': count, body
So how is it possible to group two ore more fields and make them reusable?
6 Replies
genetic-orange
genetic-orange4mo ago
At the moment, there is no API that does it as strictly as you may want. You can achieve this by creating a composite field (an object-level field that returns the multiple subfields) or by using a form component (isn't as type-safe) withForm is very strict with the values it accepts, so it cannot be extended the way you want.
correct-apricot
correct-apricotOP4mo ago
@Luca | LeCarbonator thanks. Do you know if that's something that is being work on in the near future?
You can achieve this by creating a composite field (an object-level field that returns the multiple subfields)
This would have the downside that the dirty/invalid state isn't tracked on an attribute level, right?
genetic-orange
genetic-orange4mo ago
it is! there's no timeline or place to view it at the moment, as the other framework adapters currently lack any form composition so I assume those will be the focus for the time being Yes! I haven't thought about that one before, good point! Would you like me to link the form component example then?
correct-apricot
correct-apricotOP4mo ago
that would be great
genetic-orange
genetic-orange4mo ago
* The GitHub Discussion asking about it * The initial answer of crutchcorn * The example written out To achieve type safety, you could try making the form component generic and finding some path where the form's data is exposed Something like
interface FormComponentProps<T extends YourSubsetData> {
form: {
state: {
// don't actually use these values, only use them for type inference.
values: T
}
}
}

// Reads form.state.values and sees if it's extending SubsetData
<yourForm.FormComponent form={yourForm}/>
interface FormComponentProps<T extends YourSubsetData> {
form: {
state: {
// don't actually use these values, only use them for type inference.
values: T
}
}
}

// Reads form.state.values and sees if it's extending SubsetData
<yourForm.FormComponent form={yourForm}/>
I've successfully used this with field components before, but it may also work for form components.
correct-apricot
correct-apricotOP4mo ago
Great, thank you. I will try this out.

Did you find this page helpful?