feat: callable forms#15986
Conversation
🦋 Changeset detectedLatest commit: a3640d1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
I've found myself wishing for this feature but not to replace commands but rather because only form properly handles streaming of file uploads. Using command under the hood in combination with #15978 will buffer the whole file for its JSON body. I can open a new issue for that tho (I'm aware this addition is non-trivial, devalue does not support streaming, and the form uploads use a custom protocol afaik) |
|
Yeah, would love to be able to do that. Mostly we just haven't figured out a good use-case-agnostic API for devalue to deal with async/streaming values (but then again we haven't spent a lot of time thinking about it) |
I found myself wanting to call a
formdirectly, without actually using it on a<form>. In my case specifically it was for a recursive operation — I wanted the user to invokedeleteFileas a traditional<form>, but inside the handler I wanted to be able to calldeleteFileas a function, which is currently impossible:Obviously you can work around this by yoinking the logic out into a separate function, but it's not as nice — it's less self-contained, and you need to come up with two names instead of one. I gather I'm not the only person who has encountered cases like this.
The implementation is pleasingly simple — we just call
commandunder the hood, remove theis_form_content_typecheck and it basically Just Works AFAICT? There is one change:myform.pendingneeds to becomemyform.submittingso that we can distinguish between form submissions (myform.submitting) and direct calls (myform.pending).Note that the semantics of direct calls are exactly the same as for
command:myform.fields.foo.issues()andmyform.resultdo not get populated — these only happen for form submissionsOf course, the obvious follow-up question: if we can do this, is there any point in keeping
commandaround? Two possible arguments:commandin your app and notform, you will have a very slightly smaller JS bundlecommandcan have any schema, whereasformalways has to be av.object({...})or the non-Valibot equivalentI'm personally not sure those are compelling enough reasons, but this is a conversation to have as a follow-up.
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm testand lint the project withpnpm lintandpnpm checkChangesets
pnpm changesetand following the prompts. Changesets that add features should beminorand those that fix bugs should bepatch. Please prefix changeset messages withfeat:,fix:, orchore:.Edits