Import
import { Field } from '@tanstack/svelte-form'
// or
const form = createForm(...)
// use form.Field
Props
The name of the field. Must match a key in your form’s data type.
Validation functions for the field.
Show properties
Show properties
Runs on every change
Async validation on change
Debounce time for async onChange validation
Runs when field loses focus
Runs when field is mounted
Default value for the field (overrides form defaultValues)
Svelte snippet that receives field and state as parameters
Snippet Parameters
Thechildren snippet receives an object with:
The field API instance
Show methods
Show methods
Update the field value
Mark field as touched/blurred
Get current field value
Set field value
Add item to array field
Remove item from array field
Usage
Basic Field
<script lang="ts">
import { createForm } from '@tanstack/svelte-form'
const form = createForm({
defaultValues: {
name: '',
},
onSubmit: async ({ value }) => console.log(value),
})
</script>
<form.Field name="name">
{#snippet children({ field, state })}
<label>
Name:
<input
value={state.value}
oninput={(e) => field.handleChange(e.currentTarget.value)}
onblur={field.handleBlur}
/>
</label>
{/snippet}
</form.Field>
With Validation
<form.Field
name="email"
validators={{
onChange: ({ value }) => {
if (!value) return 'Email is required'
if (!value.includes('@')) return 'Invalid email address'
return undefined
},
}}
>
{#snippet children({ field, state })}
<div>
<input
type="email"
value={state.value}
oninput={(e) => field.handleChange(e.currentTarget.value)}
onblur={field.handleBlur}
placeholder="Enter your email"
/>
{#if state.meta.isTouched && state.meta.errors.length > 0}
<em style="color: red;">{state.meta.errors[0]}</em>
{/if}
</div>
{/snippet}
</form.Field>
Async Validation
<form.Field
name="username"
validators={{
onChangeAsyncDebounceMs: 500,
onChangeAsync: async ({ value, signal }) => {
// Check if username is available
const response = await fetch(`/api/check-username?name=${value}`, {
signal,
})
const available = await response.json()
return available ? undefined : 'Username is taken'
},
}}
>
{#snippet children({ field, state })}
<div>
<input
value={state.value}
oninput={(e) => field.handleChange(e.currentTarget.value)}
/>
{#if state.meta.isValidating}
<span>Checking...</span>
{/if}
{#if state.meta.errors.length > 0}
<em>{state.meta.errors[0]}</em>
{/if}
</div>
{/snippet}
</form.Field>
Array Fields
<script lang="ts">
const form = createForm({
defaultValues: {
items: [''],
},
onSubmit: async ({ value }) => console.log(value),
})
</script>
<form.Field name="items" mode="array">
{#snippet children({ field, state })}
<div>
{#each state.value as item, i (i)}
<form.Field name={`items[${i}]`}>
{#snippet children({ field: itemField, state: itemState })}
<input
value={itemState.value}
oninput={(e) => itemField.handleChange(e.currentTarget.value)}
/>
<button type="button" onclick={() => field.removeValue(i)}>
Remove
</button>
{/snippet}
</form.Field>
{/each}
<button type="button" onclick={() => field.pushValue('')}>
Add Item
</button>
</div>
{/snippet}
</form.Field>
Standalone Field
You can use the Field component from the package directly:<script lang="ts">
import { createForm, Field } from '@tanstack/svelte-form'
const form = createForm({
defaultValues: { name: '' },
onSubmit: async ({ value }) => console.log(value),
})
</script>
<Field form={form} name="name">
{#snippet children({ field, state })}
<input
value={state.value}
oninput={(e) => field.handleChange(e.currentTarget.value)}
/>
{/snippet}
</Field>
TypeScript
The Field component is fully typed:interface FormData {
name: string
age: number
tags: string[]
}
const form = createForm<FormData>({
defaultValues: {
name: '',
age: 0,
tags: [],
},
onSubmit: async ({ value }) => console.log(value),
})
// TypeScript knows 'name' is a string
<form.Field name="name">
{#snippet children({ field, state })}
<!-- state.value is typed as string -->
<input value={state.value} />
{/snippet}
</form.Field>
// TypeScript knows 'tags' is an array
<form.Field name="tags" mode="array">
{#snippet children({ field, state })}
<!-- state.value is typed as string[] -->
<!-- field.pushValue expects a string -->
<button onclick={() => field.pushValue('')}>Add</button>
{/snippet}
</form.Field>
See Also
- createForm - Create form instances
- FieldApi - Core field API
- FieldOptions - Field configuration
- Arrays Guide - Working with array fields