Form State Management
Relevant source files
The following files were used as context for generating this wiki page:The @opensky/remotes package provides two primary helper utilities, createValidation and createEnhancedForm, designed to improve the developer and user experience when working with SvelteKit's remote form functions. These utilities introduce reactive state management for form submissions, a structured validation system with a better user experience, and a semantic callback-based approach for handling the form submission lifecycle.
This system aims to provide functionality similar to libraries like superforms but tailored for SvelteKit's remote functions. It manages form states, handles validation feedback, and facilitates complex patterns like optimistic updates and submission cancellation. The two main functions are exported from the package's entry point.
Sources: packages/remotes/README.md:3-4, packages/remotes/src/lib/index.ts:1-2
createValidation
This utility creates a helper for managing form validation state. Its primary goal is to improve the user experience by controlling when validation issues are displayed. The core logic is to show issues only when a user leaves a field (onblur) and clear them as soon as the user starts typing in that field again (oninput).
Sources: packages/remotes/src/lib/validation.svelte.ts:12-16, packages/remotes/README.md:9-11
Core Functionality
The createValidation function takes a SvelteKit RemoteForm instance as its only argument and returns an object with methods to manage validation.
Sources: packages/remotes/src/lib/validation.svelte.ts:17
API Methods
| Method | Description |
|---|---|
fields(path: string) | Returns onblur and oninput event handlers for a given field path (e.g., 'name' or 'address.city'). This registers the field for validation. |
issues(path: string) | Returns a reactive array of validation issue strings for a field path, or null if there are no issues. |
allIssues() | Returns a reactive object containing all current validation issues for all registered fields. |
addIssue(path: string, issue: string) | Manually adds a custom validation error message to a specific field. Useful for client-side validation logic. |
reset() | Clears all validation issues from the state. |
validateAll() | Triggers validation for all registered fields against the server. |
updateIssues() | Populates the local issue state from the RemoteForm's issues, typically after a form submission returns validation errors. |
Sources: packages/remotes/README.md:19-25, packages/remotes/src/lib/validation.svelte.ts:192-203
Validation Flow
The validation logic uses a combination of event handlers and debounced remote calls to provide responsive feedback without overwhelming the server.
- Field Registration: Calling
valid.fields('path')registers a field for validation tracking. - Input Event (
oninput): When the user types, it checks if the field currently has issues. If so, it runs apreflightOnlyvalidation to clear the issues as the user corrects the input. A debounced full validation is also triggered. - Blur Event (
onblur): When the user leaves a field, a debounced remote validation is triggered. It first attempts apreflightOnlycheck, and if that passes, it may perform a full server validation to get server-side errors.
This flow is illustrated below:
This diagram shows the logic flow for oninput and onblur events managed by createValidation.
Sources: packages/remotes/src/lib/validation.svelte.ts:149-181, packages/remotes/src/lib/validation.svelte.ts:70-75
createEnhancedForm
This utility builds upon SvelteKit's use:enhance by creating a state machine for the form submission lifecycle. It provides reactive state tracking and semantic callbacks for different stages of the request, such as onSubmit, onReturn, and onError. It can also integrate with a createValidation instance to automate validation feedback.
Sources: packages/remotes/README.md:63-67, packages/remotes/src/lib/enhance.svelte.ts:223-233
Form State Machine
The core of createEnhancedForm is its state management. The form can be in one of several states throughout its lifecycle. The delayed and timeout states are conditionally available based on creation options.
The possible states are:
idle: The form is ready for submission.pending: The form has been submitted and is awaiting a response.delayed: The submission is taking longer thandelayMs.timeout: The submission has exceeded thetimeoutMs.issues: The server responded with validation issues.error: The submission resulted in an error.result: The submission was successful and returned a result. (Formerly namedsuccess).
Sources: packages/remotes/src/lib/enhance.svelte.ts:31, packages/remotes/CHANGELOG.md:11
The following diagram illustrates the state transitions:
This diagram shows the possible state transitions for a form managed by createEnhancedForm.
API and Configuration
createEnhancedForm is configured at creation time and returns an object containing the enhance handler and reactive state getters.
Creation Options
| Option | Type | Description |
|---|---|---|
validation | Validation | An optional instance from createValidation for automatic issue handling. |
delayMs | number | Milliseconds to wait before transitioning to the delayed state. |
timeoutMs | number | Milliseconds to wait before transitioning to the timeout state. |
Sources: packages/remotes/src/lib/enhance.svelte.ts:44-52, packages/remotes/CHANGELOG.md:13-14
Returned Object
| Property | Type | Description |
|---|---|---|
enhance(...) | function | The form enhancement handler to be used with use:enhance. |
reset() | function | A method to manually reset the form's state to idle. |
state | string | A reactive property holding the current state string (e.g., 'pending'). |
idle, pending, issues, error, result | boolean | Reactive boolean getters for the form's state. |
delayed | boolean | A conditional boolean getter, only available if delayMs was provided. |
timeout | boolean | A conditional boolean getter, only available if timeoutMs was provided. |
Sources: packages/remotes/README.md:73-79, packages/remotes/src/lib/enhance.svelte.ts:356-465, packages/remotes/CHANGELOG.md:6
Submission Lifecycle and Callbacks
The enhance method accepts a set of optional callbacks that are executed at different points in the submission lifecycle.
This sequence diagram illustrates the flow of a form submission using createEnhancedForm and its lifecycle callbacks.
Lifecycle Callbacks
| Callback | Context | Description |
|---|---|---|
onSubmit | SubmitContext | Called before submission. Provides cancel() to halt submission and updates() for optimistic UI. |
onDelay | BaseEnhanceContext | Called if submission exceeds delayMs. Only available if delayMs is set. |
onTimeout | BaseEnhanceContext | Called if submission exceeds timeoutMs. Only available if timeoutMs is set. |
onReturn | { result } | Called on a successful submission with a result. |
onIssues | BaseEnhanceContext | Called when the server returns validation issues. |
onError | { error } | Called when the submission throws an error. |
Sources: packages/remotes/README.md:84-93, packages/remotes/src/lib/enhance.svelte.ts:90-132
The onSubmit callback is particularly powerful, as it allows for client-side cancellation and optimistic updates.
// packages/remotes/README.md:96-108
form.enhance(opts, {
onSubmit: ({ cancel, updates, data }) => {
// Custom client-side checks before submission
if (!customValidationCheck(data)) {
valid.addIssue('fieldName', 'Custom validation failed')
cancel('issues') // Cancel and set state to 'issues'
return
}
// Optimistic updates
updates(getPosts().withOverride((posts) => [newPost, ...posts]))
},
// ... other callbacks
})
Sources: packages/remotes/README.md:96-108, packages/remotes/src/lib/enhance.svelte.ts:298-307
Conclusion
The form state management system in @opensky/remotes provides a robust and developer-friendly layer on top of SvelteKit's native remote forms. createValidation offers a refined user experience for displaying validation errors, while createEnhancedForm introduces a predictable state machine and lifecycle callbacks for managing the complexities of form submissions. Together, they create a powerful, cohesive system for handling forms in a modern SvelteKit application.
Sources: packages/remotes/README.md:3-4