Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tanstack/form/llms.txt
Use this file to discover all available pages before exploring further.
Get started with TanStack Form in Svelte by creating a form instance and connecting it to your form fields.
Installation
Install the Svelte adapter for TanStack Form:
npm install @tanstack/svelte-form
The bare minimum to get started is to create a form and add a field using createForm.
Use createForm to create a form instance with default values and a submit handler:
<script>
import { createForm } from '@tanstack/svelte-form'
const form = createForm(() => ({
defaultValues: {
fullName: '',
},
onSubmit: async ({ value }) => {
// Do something with form data
console.log(value)
},
}))
</script>
The createForm function returns a reactive form store that automatically updates your UI when form state changes.
Create a form element that handles submission:
<form
onsubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
>
<!-- Fields will go here -->
</form>
Use the form.Field component with Svelte’s snippet syntax to create form fields:
<form.Field name="fullName">
{#snippet children(field)}
<input
name={field.name}
value={field.state.value}
onblur={field.handleBlur}
oninput={(e) => field.handleChange(e.target.value)}
/>
{/snippet}
</form.Field>
Complete Example
Here’s a complete working form with validation:
<script>
import { createForm } from '@tanstack/svelte-form'
const form = createForm(() => ({
defaultValues: {
fullName: '',
},
onSubmit: async ({ value }) => {
console.log(value)
},
}))
</script>
<div>
<h1>Simple Form Example</h1>
<form
onsubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
>
<div>
<form.Field name="fullName">
{#snippet children(field)}
<input
name={field.name}
value={field.state.value}
onblur={field.handleBlur}
oninput={(e) => field.handleChange(e.target.value)}
/>
{/snippet}
</form.Field>
</div>
<button type="submit">Submit</button>
</form>
</div>
Example with Multiple Fields
Here’s a more complete example with multiple fields and validation:
<script lang="ts">
import { createForm } from '@tanstack/svelte-form'
const form = createForm(() => ({
defaultValues: {
firstName: '',
lastName: '',
employed: false,
jobTitle: '',
},
onSubmit: async ({ value }) => {
alert(JSON.stringify(value))
},
}))
</script>
<form
id="form"
onsubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
>
<h1>TanStack Form - Svelte Demo</h1>
<form.Field
name="firstName"
validators={{
onChange: ({ value }) =>
value.length < 3 ? 'Not long enough' : undefined,
}}
>
{#snippet children(field)}
<div>
<label for={field.name}>First Name</label>
<input
id={field.name}
type="text"
placeholder="First Name"
value={field.state.value}
onblur={() => field.handleBlur()}
oninput={(e: Event) => {
const target = e.target as HTMLInputElement
field.handleChange(target.value)
}}
/>
{#if field.state.meta.errors}
<em>{field.state.meta.errors[0]}</em>
{/if}
</div>
{/snippet}
</form.Field>
<form.Field
name="lastName"
validators={{
onChange: ({ value }) =>
value.length < 3 ? 'Not long enough' : undefined,
}}
>
{#snippet children(field)}
<div>
<label for={field.name}>Last Name</label>
<input
id={field.name}
type="text"
placeholder="Last Name"
value={field.state.value}
onblur={() => field.handleBlur()}
oninput={(e: Event) => {
const target = e.target as HTMLInputElement
field.handleChange(target.value)
}}
/>
{#if field.state.meta.errors}
<em>{field.state.meta.errors[0]}</em>
{/if}
</div>
{/snippet}
</form.Field>
<div>
<form.Subscribe
selector={(state) => ({
canSubmit: state.canSubmit,
isSubmitting: state.isSubmitting,
})}
>
{#snippet children({ canSubmit, isSubmitting })}
<button type="submit" disabled={!canSubmit}>
{isSubmitting ? 'Submitting' : 'Submit'}
</button>
{/snippet}
</form.Subscribe>
<button type="button" onclick={() => form.reset()}>
Reset
</button>
</div>
</form>
Key Concepts
The form instance returned by createForm is a reactive Svelte store that provides:
form.Field - Component for creating form fields
form.Subscribe - Component for subscribing to form state
form.handleSubmit() - Method to submit the form
form.reset() - Method to reset the form to default values
form.useStore() - Hook to subscribe to specific form state
Field Component
The form.Field component uses Svelte’s snippet syntax and provides:
field.state.value - Current field value
field.handleChange() - Update field value
field.handleBlur() - Mark field as blurred
field.state.meta - Field metadata (errors, touched, dirty, etc.)
Subscribe Component
The form.Subscribe component lets you subscribe to specific form state to optimize rendering:
<form.Subscribe
selector={(state) => ({
canSubmit: state.canSubmit,
isSubmitting: state.isSubmitting,
})}
>
{#snippet children(state)}
<button type="submit" disabled={!state.canSubmit}>
{state.isSubmitting ? '...' : 'Submit'}
</button>
{/snippet}
</form.Subscribe>
Next Steps
Now that you have a basic form working, explore more advanced features: