T
TanStack3w ago
wise-white

Pass partial form to onBlurAsync

I'm using the form composition API. I have onBlurAsync defined in my validators. This is cool, but it validate the entire form when any field is blurred. Instead, I want to be able to only validate that field (or optionally pass other fields that should validate at the same time) How can I do this? I'd rather not have to define validators on the field level if possible
29 Replies
other-emerald
other-emerald3w ago
There's no convenient way to do that right now. Are you familiar with a library that does? Is there an API you would've liked to see?
wise-white
wise-whiteOP3w ago
Unfortunately am not familiar, just refactoring legacy forms that did not use any library. I wonder if we could access the fieldApi from onBlurAsyncif that might help? Right now it only passes formApi, but it seems like it should be able to pass fieldApi too since it triggers off a field blurring right?
other-emerald
other-emerald3w ago
hmmm ... if fieldApi was accessible, then you could only set an error for it by doing { fields: { [fieldApi.name]: 'Error' } } maybe. there's cases where fieldApi isn't available though. For blur it should be, but for change, you could have it triggered from form.setFieldValue
wise-white
wise-whiteOP3w ago
hmmm ... if fieldApi was accessible, then you could only set an error for it by doing { fields: { [fieldApi.name]: 'Error' } }
Funnily enough, that's exactly what I'm doing haha
other-emerald
other-emerald3w ago
does it work? like inconvenience aside, does the error only propagate to the selected field?
wise-white
wise-whiteOP3w ago
Oh sorry, misunderstanding. fieldApi is not accessible so I can't do that. I just meant that is the error structure that I'm using
validators: {
onBlurAsync: async ({ value }) => {
return await handleValidate({value});
},
}
validators: {
onBlurAsync: async ({ value }) => {
return await handleValidate({value});
},
}
That returns the errors in the structure you mentioned above like
{
name: 'This field is required',
lastName: 'This field is required',
}
{
name: 'This field is required',
lastName: 'This field is required',
}
If I had access to the fieldApi, I could get the name from there and then access it in value and only pass that
validators: {
onBlurAsync: async ({ value, fieldApi }) => {
return await handleValidate({value[fieldApi.name]});
},
}
validators: {
onBlurAsync: async ({ value, fieldApi }) => {
return await handleValidate({value[fieldApi.name]});
},
}
other-emerald
other-emerald3w ago
The main issue is that we can't guarantee that fieldApi is present for example, form.validate('blur') so what should happen if fieldApi is null in your validator?
wise-white
wise-whiteOP3w ago
form.validate('blur')
Oh interesting, I didn't know that was possible. In that case it'd break yeah Actually, if that were the case I'd assume you want to validate the entire form
other-emerald
other-emerald3w ago
mhm, so your proposal isn't to transform as the error returns, but to filter the values you're validating before being passed to handleValidate
wise-white
wise-whiteOP3w ago
Yes, although maybe that could work too, but I'd rather not validate fields I'm not interested in if possible That said, I'd still need to know which field was blurred
other-emerald
other-emerald3w ago
well, since it's not guaranteed to be there, there's not much harm in passing it I reckon I doubt this locks in some problem that v2 will have to break
wise-white
wise-whiteOP3w ago
The fieldApi you mean? That would be awesome!
other-emerald
other-emerald3w ago
yeah we're quite busy with the Tanstack Start RC breaking some of our stuff, as well as some other fixes. It might take a while before this is added
wise-white
wise-whiteOP3w ago
That's okay. How complex would you say this is? Is it something that someone with 0 familiarity of the codebase might be able to easily contribute? (ie. me?)
other-emerald
other-emerald3w ago
somewhat complicated. Mostly because validation is one of the older systems in the codebase, and it has accumulated some tech debt the types should be straightforward
wise-white
wise-whiteOP3w ago
Haha, okay, I think I'll wait. Thank you so much!
other-emerald
other-emerald3w ago
thanks for reaching out
wise-white
wise-whiteOP2w ago
@Luca | LeCarbonator I have a follow-up question: Since I am now calling the validation using onBlurAsync at the field level, when I submit the form, this causes ALL of them to run again, hitting my endpoint multiple times. I see that this is intentional, but is there any way around it? I'd like to validate them all at once (one call to the validation endpoint) rather than each one individually on submit
other-emerald
other-emerald2w ago
well, the clean solution would be the stuff we discussed above. As for a workaround right now, a debouncer, throttler or rate limiter. Check out the TanStack Pacer example if you want a good visual on what these would actually do: https://stackblitz.com/edit/tanstack-pacer-7brrdo9m?file=README.md
LeCarbonator
StackBlitz
Pacer Util Comparison Example (duplicated) - StackBlitz
Run official live example code for Pacer Util Comparison, created by Tan Stack on StackBlitz
other-emerald
other-emerald2w ago
actually, your endpoint's getting called with different parameters every time, no?
wise-white
wise-whiteOP2w ago
Yup, it is. If possible I'd like to combine them into one when submitting
other-emerald
other-emerald2w ago
Sounds like something that's out of scope then. Even with the proposed feature of having fieldApi?: in the form validators, this would have to be addressed
wise-white
wise-whiteOP2w ago
Ok, ideally it would just be an option that said "don't validate everything individually on submit"
other-emerald
other-emerald2w ago
but how would your batched request look like? are you assuming that it will just be correct on submit?
wise-white
wise-whiteOP2w ago
Sorry, to be specific, I have onSubmit and then in validators I have onSubmitAsync: handleValidate which is validating the entire form So my understanding is the validator gets called first with the entire form, and if it's good then onSubmit is called right?
other-emerald
other-emerald2w ago
correct it goes through all listed validators again before calling onSubmit, and only does so if the validators succeeded
wise-white
wise-whiteOP2w ago
Got it. So in that step, I'm actually already calling the validation endpoint with the entire form, so I don't need it to go through all the field-level validators To summarize: My form has a lot of async validation and it'd be rough to call the endpoint that many times on submit Haha, is this hacky or not recommended for any reason? It seems to be working: In my field validator function (the one I pass to onBlurAsync), I'm checking the form.state.isSubmitting and returning early based on that
other-emerald
other-emerald2w ago
shouldn't cause race conditions if that's what you mean with hacky. As far as code goes, I wouldn't recommend the approach in general. However, this should all clean up more once the feature's in
wise-white
wise-whiteOP2w ago
Nice, thanks again!

Did you find this page helpful?