Is there a way to get the type of a form and form state from form options?
I'm trying to create a generic stepper form where certain parts are only visible if other parts are complete or have certain answers. Currently I'm doing this with nested
<form.Subscribe>
components, but it's pretty ugly. I'm hoping to do something like this:
But I'm not sure how to type Form
and FormState
. It looks like it's possible by kind of duplicatign the type of createFormHooks
, but it ends up with like 9 generics and it's just nasty. I'm wondering if there's a better built-in way to do this (some type that gives the return type of useAppForm
given the form options?) or if I'm going about this all wrong and should be taking a different approach.13 Replies
graceful-blue•2mo ago
Stepped forms are not a feature yet, but it may be in the future ( https://github.com/TanStack/form/issues/419 )
For now, I recommend using one form for each step instead of grouping all steps into one. The reason is that form validators would consider all fields, even ones that haven‘t „rendered“ yet
GitHub
[Feature Request]: Form Groups · Issue #419 · TanStack/form
Description When building a form stepper, like so: It's common for each step to have its own form. However, this complicates the form submission and validation process by requiring you to add c...
harsh-harlequinOP•2mo ago
Interesting. Multiple forms would work, I'm just not sure how I'd handle submissions. Like how to trigger the submit validations on all the sub-forms when the final "submit" butotn gets clicked, how to bubble up the form data, etc
graceful-blue•2mo ago
oh, so you only have validation at the very end? Apologies, I assumed you validate on every step
one form can work for that
if you have it on every step, you would store the successful steps as values to ensure users don‘t change them afterwards
harsh-harlequinOP•2mo ago
I see, so if I validated at each step, it could sort of be like a "wizard" flow where the "next step" button actually submits the form, which then validates the data and passes the validated data up to the parent component via a callback prop?
graceful-blue•2mo ago
yes!
but if instead the step button changes a field value and there‘s one submission, then one form‘s the way to go
harsh-harlequinOP•2mo ago
I gotcha. Stepper wasn't the right word for the UI I'm going for, it's more like a form where a section doesn't show unless the previous section has been answered and is in a certain state. For example, the first question is something like
Is this an emergency?
If the user selects "no", we show a contact information form. The last question in the contact info form is like "are you willing to answer some questions here or would you rather us call you", and if they select "yes" for that one it shows more questions. So they aren't really discrete steps that are shown in a wizard, more like a form that continuously updates as you answer more of it.
And ideally I'd like to be able to do it without having the entire form component rerender every time any of that state changes, though that may not be possible right now.graceful-blue•2mo ago
the form hook itself is stable, and if you subscribe to the step value only then the rerender would only happen within that section
but yes, it‘s not possible right now. If you have API ideas for it, let us know!
harsh-harlequinOP•2mo ago
The main thing I had in mind is exposing a
FormType<typeof useAppForm, typeof formOptions>
generic that gives you the type of the return value of useAppForm(formOptions)
. I think it's possible to implement right now by doing something like this:
Plus the addition of taking a second generic (typeof useAppForm) and inerring TComponents
and TFormComponents
, but it's pretty gnarly.
Plus AppFieldExtendedReactFormApi
is not exported and I'm not sure if it's subject to change.
But basically it would allow creating more generic components that are still typesafe with the specific form you're using them on. For example, right now I have a RenderIfTrue
component that looks like this:
This works but I'd have to implement it for each individual form in my app. If it was easy to get the form type and form state type using the form options, the component could be made to work with any form, something like this:
But I might just be thinking about how the works wrong on a conceptual levelgraceful-blue•2mo ago
don't worry about the typing and implementation. I meant what would an ideal scenario look like for you
harsh-harlequinOP•2mo ago
Ideally I'd be able to something like this:
Just being able to pass any form in the standard way as a component prop, and have the component be typesafe
graceful-blue•2mo ago
The goal is to purposefully not have to do that. See the philosophy section https://tanstack.com/form/latest/docs/philosophy
Philosophy | TanStack Form Docs
Every well-established project should have a philosophy that guides its development. Without a core philosophy, development can languish in endless decision-making and have weaker APIs as a result. Th...
harsh-harlequinOP•2mo ago
The part about not having to specify generics right? That makes sense, but in the case of creating generic form functions, the generics would be automatically inferred when you use the component just based on what you pass as the
form
prop no? And without something like that, is there a way to create generic components that can be used with any form in the app in a typesafe way? I've gotten myself into generic hell with react-hook-form
, so I appreciate the philosophy, and if there's another way to do something like this I'm all ears.graceful-blue•2mo ago
well, you have some helper types.
AnyFieldApi
and AnyFormApi