form
form copied to clipboard
feat(react-form): add fieldOptions and dynamicFieldOptions APIs
Related to #1202 Add fieldOptions and dynamicFieldOptions APIs that allow creating fieldOptions outside of JSX/html...
Implementation:
export const interestFormOpts = formOptions({
defaultValues: {
fullName: '',
interests: [
{
name: '',
level: 0,
},
],
},
})
// static field options
const fullNameOptions = fieldOptions({
formOptions: { ...interestFormOpts },
name: 'fullName',
validators: {
onChange: ({ value }) => {
if (value === '') {
return 'Full name is required'
}
},
},
})
...
// dynamic field options
const interestLevelOptions = dynamicFieldOptions((idx: number) => ({ // parm can be of any type allowing dynamic usage!
formOptions: { ...interestFormOpts },
name: `interests[${idx}].level`,
listeners: {
onChange: ({ value, fieldApi }) => {
if (value > 9000) {
fieldApi.form.setFieldValue(`interests[${idx}].name`, 'Vegeta')
}
},
},
}))
export const fieldConfig = {
fullName: fullNameOptions,
interests: interestsOptions,
interestName: interestNameOptions,
interestLevel: interestLevelOptions,
}
Usage in form:
// static fieldOptions usage
<form.AppField
{...fieldConfig.fullName}
children={(field) => <field.TextField label="Full Name" />}
/>
...
// dynamic fieldOptions usage
{interestsField.state.value.map((_, idx) => (
...
<form.AppField
{...fieldConfig.interestLevel(idx)}
children={(interestLevelField) => (
<interestLevelField.TextField label="Interest Level" />
)}
/>
</div>
))}
Why?
-
Keep validation and listener logic out of JSX The primary advantage is the clean separation of form validation and field behavior from component rendering code. This allows for leaner JSX without the need to define the configuration inline.
-
Centralized Tanstack Form Fields Configuration Field configurations, validators, and behaviors can be defined in one central location, making it much easier to understand a form's complete behavior without navigating through scattered JSX files.
-
Dynamic Configuration Support The ability to define configurations as functions (with arbitrary parameters) enables dynamic field configurations as needed! Developers can create configurations that adapt based on indices (perfect for field arrays) or other variables.
-
All done with Type Safety With the implementation in this PR we provide strong TypeScript support with preserved type information throughout the configuration. This ensures that field-specific validators receive the correct value types and that configurations maintain their defined structure.