You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Form.submit (and the form mixin) accept a handler that replaces the default fetch.
Useful when the client talks to an API directly instead of a Remix action.
<formmix={form(loginForm,{asynchandler(data,signal){awaitapi.post('/v1/login',data,{ signal });},})}>{/* … */}</form>
Possible objections
Why not native HTML constraints?
Native constraints (required, minLength, type, …) work without JavaScript. They are a good first line of defense, not the validation API.
They do not share a schema with the server
They do not produce typed, renderable field errors
They do not cover cross-field rules, coerced values, or file validation
Browser validation UI is inconsistent and hard to style
This package sets noValidate and runs the same schema on the client that the action runs on the server. Without JavaScript, the browser still POSTs FormData and the server still restores the form via toDraft and toErrors. Native attributes stay available for accessibility (type, aria-required). Deriving constraints from the schema is complementary and can be added later. The schema is the source of truth.
Why FormData?
A no-JS form submit is FormData (application/x-www-form-urlencoded or multipart/form-data). Remix actions already receive that. Files require it.
A JSON (or typed-object) request body would split the API: one path with JavaScript, another without. FormData is the request. The schema parses it. The client-side API does not keep a separate values object.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
This proposal describes a first-party unified API for progressively enhanced FormData-based actions.
The problem
A great form user experience requires more than returning an HTTP response.
Users already expect live feedback as they interact with a form:
In addition, form libraries in other frameworks have set a floor for what developers expect:
Proposal
Ship a first-party
remix/formpackage built on three primitives:Formhandles state, validation, and submit.Fieldhandles per-field value, error, and change events.formmixin wires a<form>to aForminstance.Use cases
Navigational forms
Formis the core API for state management, validation, and submit handling.stateprovides live errors and pending status for instant feedback.Fieldis the API for field-level management.formmixin handles the submit event: it runs the client-side validation before submitting and resets the form after a successful result.toDraftandtoErrorsturnFormDataand schema issues into draft and error props so an action can re-render the form with values and errors intact.Non-navigational forms
formmixin lets the browser submit the form (andremix/uihandles the navigation).navigate: falseprevents that navigation and submits withfetchto the form's action instead.submitcompletelistener can then reload the frame to revalidate displayed data.e.waitUntilkeepspendingtrue until the reload finishes.Imperative non-navigational forms
Form.submit()can run without a<form>submit event.Reacting to field changes
Fieldis an event target. Listen forchangeto react when the field value updates.Optimistic UI
Form.state.submissionholds the in-flight submission data and is cleared when the submission ends.e.waitUntilkeeps the optimistic value until the frame reload completes.Custom handlers
Form.submit(and theformmixin) accept ahandlerthat replaces the default fetch.Possible objections
Why not native HTML constraints?
Native constraints (
required,minLength,type, …) work without JavaScript. They are a good first line of defense, not the validation API.This package sets
noValidateand runs the same schema on the client that the action runs on the server. Without JavaScript, the browser still POSTs FormData and the server still restores the form viatoDraftandtoErrors. Native attributes stay available for accessibility (type,aria-required). Deriving constraints from the schema is complementary and can be added later. The schema is the source of truth.Why FormData?
A no-JS form submit is FormData (
application/x-www-form-urlencodedormultipart/form-data). Remix actions already receive that. Files require it.A JSON (or typed-object) request body would split the API: one path with JavaScript, another without. FormData is the request. The schema parses it. The client-side API does not keep a separate values object.
Resources
packages/form.All reactions