https://stackblitz.com/edit/tanstack-form-gecmjp4w?file=src%2Findex.tsx
How to handle conditional fields, when visible is false, lastName should not validate here.
24 messages · Page 1 of 1 (latest)
https://stackblitz.com/edit/tanstack-form-gecmjp4w?file=src%2Findex.tsx
How to handle conditional fields, when visible is false, lastName should not validate here.
I think you'd be better off explicitly setting lastName to nullable or optional. Doing something like this:
You can also do discriminated unions if needed, but that'd be overkill for something this simple.
See example here:
https://stackblitz.com/edit/tanstack-form-zd9iccna?file=src%2Findex.tsx
Note the listener that sets lastName to null onChange if visible is false, this is key.
Oh, that's great, thank you! I'll mess about with this with the issue I'm having tomorrow, hopefully this fixes it.
Thanks so much!
You're welcome 😄
Sorry to ask another Q, I've just been messing around a bit with it, how would I do that type of refining on a field-basis (where I don't use a schema for the validation)
I suppose this is more of a Zod Q.
https://stackblitz.com/edit/tanstack-form-syy1n5ms?file=src%2Findex.tsx
If you're depending on other fields, you can't directly add a refine the the subfield.
For this reason you see that i added the refine at the object level.
You can, however, set a refine on the object level and target a field in the object for error placement. You can see I set the path on the refine to point to one of the fields.
So if I move to the field level I can't have a dependency on another field?
<form.Field
name="lastName"
validators={{
onSubmit: z
.string()
.min(3, '[Zod] You must have a length of at least 3')
.nullable(),
// TODO: if visible is true
}}
>
I meant if you have a form level schema, you'd have to refines on the zod schema itself. If you want to have zod schemas at the field level, you can also use refine, however note you can pass in a function that returns a schema. The parameters for the onSubmit allow you to grab the fieldApi, which you can use to grab other field values!
Does that make sense? So then you can build the schema on the fly.
Yes, I think I got it! Thanks again.
https://stackblitz.com/edit/tanstack-form-syy1n5ms?file=src%2Findex.tsx
Just one last question, if I immediately press "Submit", I get an error as expected on lastName, but I cannot clear that error even if I change visible to false, I can no longer submit. Is there something I can do to reset the form errors?
I think this might be related to the issue I've been posting about in #form
For now you'd need to trigger (validate) the lastName field somehow...
Oh I see, if you’re experiencing similar things that’s all good then. Thanks again
To be honest, I don’t know why fields that are not in the DOM are even validated
It’s because the library doesn’t necessarily depend on the DOM, it’s how we also achieve the ability to work cross frameworks like React and so on!
I think it’s a bit better that way you have less implicit behavior you can’t control
For field level validations it's not my experience at all that fields that are not mounted are being validated, it's the fieldMeta is not being cleared out so existing errors prevent the form from submitting. You would have to manually reset the fieldMeta when you unmount the field.
Oh, interesting, I'll keep that in mind when I take a look later. I assume there is a function for that. Thanks!
yes there is setFieldMeta on the form api.
IMO it would be great if the library could somehow do this by default.
For me it’s still coming up with an error even when I set the fieldMeta, I must be using it wrong
For me it just keeps the same values somehow before and after reset
It's this 100%. Not only does the DOM detachment allow us to support UI components and RN, but it also enables hidden inputs et al
We did in the past and removed it because it was much harder to reason about for a FW agnostic library like ours.
We're adding the ability to make custom form.Field components soon, and you can easily add a cleanup on a useEffect to remove values in that setup
Okay I’ll wait on that then, thanks
I’ve had some success with this in the mean time:
export const createConditionalValidator = (
fieldName: string,
validator: ZodType,
falsy?: boolean,
) => {
return ({
value,
fieldApi,
}: {
value: unknown;
fieldApi: FieldApi<any, any, any, any, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
}) => {
const fieldValue = fieldApi.form.getFieldValue(fieldName);
const isEmpty = Array.isArray(fieldValue)
? fieldValue.length === 0
: !fieldValue;
const isConditionMet = falsy ? isEmpty : !isEmpty;
if (isConditionMet) {
const parseResult = validator.safeParse(value);
if (!parseResult.success) {
return parseResult.error.errors[0].message;
}
}
return undefined;
};
};