Quick Start Guide
Relevant source files
The following files were used as context for generating this wiki page:The @opensky/remotes package provides helper utilities for SvelteKit to improve the developer and user experience when working with remote form functions. It is designed to simplify form validation and state management during submission lifecycles.
The library exports two primary helper functions: createValidation and createEnhancedForm. createValidation focuses on providing a better user experience for displaying field validation issues. createEnhancedForm creates a tracked state for the remote form and offers semantic callbacks for different stages of the form submission request. These two helpers can be used together for a comprehensive form management solution.
Sources: README.md:3-4, packages/remotes/package.json:3, packages/remotes/src/lib/index.ts:1-2
createValidation
This helper is used to manage form validation logic and state. Its primary goal is to improve the user experience by controlling when validation issues are displayed. The logic dictates that issues for a field only appear when the user leaves the field (onblur event) and are cleared as soon as the user starts typing in the field again (oninput event).
Sources: README.md:8-10, packages/remotes/src/lib/validation.svelte.ts:10-12
Usage
To use it, import createValidation and pass your SvelteKit remoteForm instance to it.
import { createValidation } from '@opensky/remotes'
const valid = createValidation(remoteForm)
Sources: README.md:15-17
The createValidation function returns an object with several methods to manage validation.
| Method | Description |
|---|---|
fields(path: string) | Returns onblur and oninput event handlers to bind to a form field. Registers the field for validation. |
issues(path: string) | Returns an array of validation issue strings for a given field path, or null if there are no issues. |
allIssues() | Returns an 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. |
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 for all registered fields. |
Sources: README.md:21-27, packages/remotes/src/lib/validation.svelte.ts:203-211, packages/remotes/CHANGELOG.md:6
Field Validation Flow
The diagram below illustrates the validation lifecycle for a single input field managed by createValidation.
Example
You bind the handlers from valid.fields() to your input and use valid.issues() to conditionally display error messages and styles.
<script lang="ts">
import { createValidation } from '@opensky/remotes';
import { myForm } from './myForm.remote';
const valid = createValidation(myForm);
</script>
<input
{...myForm.fields.name.as('text')}
{...valid.fields('name')}
class:border-red-500={valid.issues('name')}
/>
{#if valid.issues('name')}
{#each valid.issues('name') as issue}
<p>{issue}</p>
{/each}
{/if}
Sources: README.md:33-44
createEnhancedForm
This helper creates a reactive state machine for a remote form, providing granular control and visibility into the form submission lifecycle. It simplifies handling different stages of a request, such as pending, delayed, and timeout states, and provides semantic callbacks for each stage.
Sources: README.md:59-60, packages/remotes/src/lib/enhance.svelte.ts:200-205
Usage
Import createEnhancedForm, pass the remoteForm instance, and optionally provide configuration options.
import { createEnhancedForm } from '@opensky/remotes'
const form = createEnhancedForm(remoteForm, {
validation: valid, // Optional: instance from createValidation
delayMs: 500, // Optional: time until 'delayed' state
timeoutMs: 3500 // Optional: time until 'timeout' state
})
Sources: README.md:66-71, commit-message.txt:3-6
Creation Options
The behavior of createEnhancedForm can be configured at creation time.
| Option | Type | Description |
|---|---|---|
validation | Validation | An optional instance from createValidation. If provided, createEnhancedForm will automatically call updateIssues() on a validation issue response and validateAll() on an error. |
delayMs | number | Milliseconds to wait before the form state transitions from pending to delayed. If provided, the delayed state and onDelay callback become available. |
timeoutMs | number | Milliseconds to wait before the form state transitions to timeout. If provided, the timeout state and onTimeout callback become available. |
Sources: README.md:77-80, packages/remotes/src/lib/enhance.svelte.ts:54-62, commit-message.txt:3-9
Form State Lifecycle
The form.state property transitions through various states during submission. The delayed and timeout states are only possible if delayMs and timeoutMs are configured, respectively.
This diagram shows the possible state transitions of the enhanced form during and after a submission.
Sources: packages/remotes/src/lib/enhance.svelte.ts:35, packages/remotes/src/lib/enhance.svelte.ts:245-303, commit-message.txt:4-5
API and Callbacks
The returned form object contains the enhance method, state getters, and a reset function.
Returned Object:
| Property | Description |
|---|---|
enhance(params, callbacks) | The form enhancement handler to be used with SvelteKit's enhance. |
reset() | A method to manually reset the form's state back to idle. |
state | A reactive string representing the current state (e.g., 'idle', 'pending', 'result'). |
idle, pending, issues, error, result | Boolean getters for the current state. |
delayed | A boolean getter, only available if delayMs was provided. |
timeout | A boolean getter, only available if timeoutMs was provided. |
Sources: README.md:73-76, packages/remotes/CHANGELOG.md:4
Enhance Callbacks:
| Callback | Description |
|---|---|
onSubmit | Called before submission. Receives cancel() to halt submission and updates() for optimistic UI. |
onDelay | Called if submission exceeds delayMs. Only available if delayMs is set. |
onTimeout | Called if submission exceeds timeoutMs. Only available if timeoutMs is set. |
onReturn | Called on a successful submission. Receives the result. |
onIssues | Called when the server returns validation issues. |
onError | Called when the submission promise rejects with an error. |
Sources: README.md:83-93, packages/remotes/src/lib/enhance.svelte.ts:93-111
Combined Example
Here is a full example demonstrating how createValidation and createEnhancedForm work together. The validation instance is passed to createEnhancedForm, which automates the process of updating validation state based on the form's submission lifecycle.
Sources: README.md:112-114
<script lang="ts">
import { createValidation, createEnhancedForm } from '@opensky/remotes'
import { myForm } from './myForm.remote'
import { z } from 'zod'
const schema = z.object({
name: z.string().min(4, 'Too short').max(10, 'Too long'),
address: z.object({
state: z.string()
})
})
// 1. Create validation helper
const valid = createValidation(myForm)
// 2. Create enhanced form, passing the validation helper
const form = createEnhancedForm(myForm, {
validation: valid,
delayMs: 500,
timeoutMs: 3500
})
</script>
<p>State: {form.state}</p>
<!-- 3. Use the enhance handler -->
<form {...myForm.preflight(schema).enhance(opts =>
form.enhance(opts, {
onDelay: () => console.log('showing loader'),
onTimeout: () => console.log('request timeout'),
onReturn: ({ result }) => console.log('success', result)
})
)}>
<input
{...myForm.fields.name.as('text')}
{...valid.fields('name')}
class:error={valid.issues('name')}
/>
{#if valid.issues('name')}
{#each valid.issues('name') as issue}
<p class="error">{issue}</p>
{/each}
{/if}
<input
{...myForm.fields.address.state.as('text')}
{...valid.fields('address.state')}
class:error={valid.issues('address.state')}
/>
<button disabled={form.pending || form.delayed}>
{form.delayed ? 'Loading...' : 'Submit'}
</button>
</form>
{#if form.timeout}
<p>Request timed out</p>
{/if}
Sources: README.md:116-170