T
TanStack8mo ago
rival-black

how to disable field based async validation if value === defaultValue

hi, i try to disable async validation (ask the server if the value exists) if the current value is the defaultValue of this field. i want to use:
//...
onChangeAsync: ({value, fieldApi}) => {
if(value === fieldApi.form.options.defaultValues[fieldApi.name]) {
return undefined;
// (or null or true, i actuallay dont know what the yup adapter needs)
}
return anyYupSchema;
}
//...
//...
onChangeAsync: ({value, fieldApi}) => {
if(value === fieldApi.form.options.defaultValues[fieldApi.name]) {
return undefined;
// (or null or true, i actuallay dont know what the yup adapter needs)
}
return anyYupSchema;
}
//...
but i got everytime "Invalid Form Values" and validation does not work. i think the return for the validation adapter should be different. i tried also with updating the field options at form level with fieldApi.update(updatedOptions) but i think there is maybe a bug‽ after updating the field options, the meta field errors is undefined or null (cant remember) instead of an empty array like after initialisation.
6 Replies
rival-black
rival-blackOP7mo ago
any ideas 💡?
genetic-orange
genetic-orange7mo ago
Does it work without the condition?
onChangeAsync: ({value, fieldApi}) => {
return anyYupSchema;
}
onChangeAsync: ({value, fieldApi}) => {
return anyYupSchema;
}
If so you should be able to do this:
onChangeAsync: ({value, fieldApi}) => {
if (value === fieldApi.form.options.defaultValues[fieldApi.name]) {
return false;
}

return anyYupSchema;
}
onChangeAsync: ({value, fieldApi}) => {
if (value === fieldApi.form.options.defaultValues[fieldApi.name]) {
return false;
}

return anyYupSchema;
}
rival-black
rival-blackOP7mo ago
nope, if i understand correctly, if there is an validationAdapter given, the internal logic skips the interpretation of the callback function for validation and run immediately .validate() on it. this will fail because the callback ({value, fieldApi}) => {} does not have it if it is run as IIFE. u can see that in: https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L561
GitHub
form/packages/form-core/src/FieldApi.ts at main · TanStack/form
🤖 Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit. - TanStack/form
genetic-orange
genetic-orange7mo ago
I'm not sure you're going for the best solution atm… maybe you can do something like this? https://stackoverflow.com/a/49494370 So you can just pass a yup object(?) to onChangeAsync and you do not need to know about the internals of the onChangeAsync function…
rival-black
rival-blackOP7mo ago
first of all, thanks for the help if i pass the whole yup form-schema via formApi this would work but in my case i need this at fieldApi level. but for now i think i have a soloution for me. I was not aware that yup throws an error object in case of invalidity. the fieldapi "catches" this throw and returns “Invalid Form Values” as string if it is typeof rawError != string (https://github.com/TanStack/form/blob/f139b6b82bd4a8cb9d63be5362b7dfdfb116322e/packages/form-core/src/FieldApi.ts#L1064) i just didn't see it because that yup throws instead of returning the error as a string. i just catch it and throw the message back now, that's how it works. i find it slightly confusing and not so transparent. i think passing the original error would provide more flexibility.
validators={{
onChange: yup
.string()
.min(3, 'First name must br at least 3 characters'),
onChangeAsyncDebounceMs: 500,
onChangeAsync: async ({ value, fieldApi }) => {
const { defaultValues } = fieldApi.form.options;
if (
defaultValues !== undefined &&
defaultValues[fieldApi.name] === value
) {
// no validation
return false;
}

try {
await yup
.string()
.min(5, 'min')
.max(7, 'max')
.validate(value);

return false;
} catch (error) {
return error.message;
}
},
}}
validators={{
onChange: yup
.string()
.min(3, 'First name must br at least 3 characters'),
onChangeAsyncDebounceMs: 500,
onChangeAsync: async ({ value, fieldApi }) => {
const { defaultValues } = fieldApi.form.options;
if (
defaultValues !== undefined &&
defaultValues[fieldApi.name] === value
) {
// no validation
return false;
}

try {
await yup
.string()
.min(5, 'min')
.max(7, 'max')
.validate(value);

return false;
} catch (error) {
return error.message;
}
},
}}
genetic-orange
genetic-orange7mo ago

Did you find this page helpful?