T
TanStack4w ago
conscious-sapphire

Better handle for conditional fields with error

Currently it's very cumbersome to use conditional fields, since there's no convenient way to handle errors on them. For example in 99% of the cases we want behavior like this: When all visible (mounted) fields are valid, despite some of the hidden fields have errors, it is considered a valid state. But currently the hidden field's error count as invalid state. Maybe changing the default behavior to ignore hidden field's error or adding option toFormOptions that determines if the form is valid/submittable or not might help?
11 Replies
foreign-sapphire
foreign-sapphire4w ago
Can you make the hidden fields optional? I ran into something similar in my current project, and had to make the fields optional unless they were indeed supposed to be validated (for example, if selecting an option from another input made them visible)
conscious-sapphire
conscious-sapphireOP4w ago
Can you elaborate on that? My current situation is like this: - There are some fields (Let's call it C.1 and C.2) that depends it's visibility on other fields (P) - There's error on C.1 - I changed P1 to other value so C.1 is hidden / C.2 is visible - I try to submit. There's no errors on visible fields (C.2 and P) - But there's hidden error state in C.1, so it's not in submittable state
stormy-gold
stormy-gold4w ago
how did you define your validation?
conscious-sapphire
conscious-sapphireOP4w ago
Here's basic reproduction
No description
conscious-sapphire
conscious-sapphireOP4w ago
export function ExampleForm() {
const form = useForm({
defaultValues: {
p: true,
c: { a: '', b: '' },
},
});

return (
<form>
<form.Field name="p">
{(field) => <Checkbox checked={field.state.value} onCheckedChange={field.handleChange} />}
</form.Field>
<form.Subscribe selector={(state) => state.values.p}>
{(p) =>
p ? (
<form.Field name="c.a" validators={{ onChange: z.string().min(1, 'Should be at least 1 characters') }}>
{(field) => <TextField value={field.state.value} onValueChange={field.handleChange} />}
</form.Field>
) : (
<form.Field name="c.b">
{(field) => <TextField value={field.state.value} onValueChange={field.handleChange} />}
</form.Field>
)
}
</form.Subscribe>
</form>
);
}
export function ExampleForm() {
const form = useForm({
defaultValues: {
p: true,
c: { a: '', b: '' },
},
});

return (
<form>
<form.Field name="p">
{(field) => <Checkbox checked={field.state.value} onCheckedChange={field.handleChange} />}
</form.Field>
<form.Subscribe selector={(state) => state.values.p}>
{(p) =>
p ? (
<form.Field name="c.a" validators={{ onChange: z.string().min(1, 'Should be at least 1 characters') }}>
{(field) => <TextField value={field.state.value} onValueChange={field.handleChange} />}
</form.Field>
) : (
<form.Field name="c.b">
{(field) => <TextField value={field.state.value} onValueChange={field.handleChange} />}
</form.Field>
)
}
</form.Subscribe>
</form>
);
}
Also noticed even if there's no mounted field, the form.fieldInfo.instance is not cleaned up. Is there any programmatic way to determine if a field has any mounted instance? Related to the original problem - in the case where hidden fields are not expected to be submitted, it would be convenient if there's some sort of API that lets onSubmit callback to only return visible fields' values. Maybe marking if it should be ignored from validation/submission when it's unmounted on each field? The tricky part is that in most case we don't want to scrap the field's data completely - so the field state could be restored when it's mounted again.
stormy-gold
stormy-gold4w ago
you can check with getFieldInfo().instance but if you want to programmatically delete fields, you can use deleteField but overall, if dynamic fields are a concern (and unmounted fields should be considered gone), then you should stick to form-level validation instead of field-level
conscious-sapphire
conscious-sapphireOP4w ago
Strangely the instance is not cleared even when all fields are unmounted.
stormy-gold
stormy-gold4w ago
:Hmm: that's strange. Can you create a reproducible example of it?
stormy-gold
stormy-gold4w ago
thanks a lot! I‘ll check it out in a bit
conscious-sapphire
conscious-sapphireOP4w ago
Yeah thank you as always for your great work ❤️ Also please consider above proposal or its alternatives... since RHF only accounts mounted fields' error for isValid

Did you find this page helpful?