Skip to main content
The Field component provides a declarative way to render form fields in Solid applications.

Import

import { Field } from '@tanstack/solid-form'
// or access via form API
const form = createForm(...)
// <form.Field ... />

Props

form
FormApi<TParentData>
required
The parent form API instance.
name
TName
required
The field name as a path string (e.g., ‘user.firstName’ or ‘items[0].name’).
defaultValue
TData
The default value for the field.
validators
FieldValidators<TParentData, TName, TData>
Validation functions for the field.
validators.onChange
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs on every change.
validators.onChangeAsync
FieldAsyncValidateOrFn<TParentData, TName, TData>
Async validator that runs on change.
validators.onChangeAsyncDebounceMs
number
Debounce time in milliseconds for async validation.
validators.onBlur
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs when the field loses focus.
validators.onMount
FieldValidateOrFn<TParentData, TName, TData>
Validator that runs when the field is mounted.
asyncDebounceMs
number
Debounce time in milliseconds for async validation. Default is 500ms.
asyncAlways
boolean
If true, async validation runs even if sync validation fails.
children
(field: Accessor<FieldApi<...>>) => JSXElement
required
A render prop function that receives the field API accessor.

Children Function Parameters

field
Accessor<FieldApi<TParentData, TName, TData>>
An accessor function that returns the field API instance.
field().name
TName
The field name.
field().state
FieldState<TData>
The current field state.
field().state.value
TData
The current field value.
field().state.meta
FieldMeta
Field metadata including errors, touched status, etc.
field().handleChange
(value: TData) => void
Update the field value.
field().handleBlur
() => void
Mark the field as touched.
field().pushValue
(value: TData extends Array<infer U> ? U : never) => void
Add a value to an array field.
field().removeValue
(index: number) => void
Remove a value from an array field.

Usage Example

Basic Field

import { createForm } from '@tanstack/solid-form'
import { Show } from 'solid-js'

function App() {
  const form = createForm(() => ({
    defaultValues: {
      firstName: '',
    },
    onSubmit: ({ value }) => {
      console.log(value)
    },
  }))

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault()
        form.handleSubmit()
      }}
    >
      <form.Field name="firstName">
        {(field) => (
          <div>
            <label for={field().name}>First Name:</label>
            <input
              id={field().name}
              name={field().name}
              value={field().state.value}
              onInput={(e) => field().handleChange(e.currentTarget.value)}
              onBlur={() => field().handleBlur()}
            />
          </div>
        )}
      </form.Field>
      <button type="submit">Submit</button>
    </form>
  )
}

Field with Validation

import { createForm } from '@tanstack/solid-form'
import { Show } from 'solid-js'

function App() {
  const form = createForm(() => ({
    defaultValues: {
      email: '',
    },
    onSubmit: ({ value }) => {
      console.log(value)
    },
  }))

  return (
    <form.Field
      name="email"
      validators={{
        onChange: ({ value }) => {
          const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
          return !emailRegex.test(value) ? 'Invalid email address' : undefined
        },
        onChangeAsync: async ({ value }) => {
          await new Promise((resolve) => setTimeout(resolve, 1000))
          return value.includes('test') ? 'Test emails not allowed' : undefined
        },
        onChangeAsyncDebounceMs: 500,
      }}
    >
      {(field) => (
        <div>
          <label for={field().name}>Email:</label>
          <input
            id={field().name}
            value={field().state.value}
            onInput={(e) => field().handleChange(e.currentTarget.value)}
            onBlur={() => field().handleBlur()}
          />
          <Show when={field().state.meta.isTouched && field().state.meta.errors.length > 0}>
            <div style={{ color: 'red' }}>{field().state.meta.errors[0]}</div>
          </Show>
          <Show when={field().state.meta.isValidating}>
            <div>Validating...</div>
          </Show>
        </div>
      )}
    </form.Field>
  )
}

Array Field

import { createForm } from '@tanstack/solid-form'
import { Index, Show } from 'solid-js'

function App() {
  const form = createForm(() => ({
    defaultValues: {
      people: [] as Array<{ name: string; age: number }>,
    },
    onSubmit: ({ value }) => {
      alert(JSON.stringify(value))
    },
  }))

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault()
        form.handleSubmit()
      }}
    >
      <form.Field name="people">
        {(field) => (
          <div>
            <Show when={field().state.value.length > 0}>
              <Index each={field().state.value}>
                {(_, i) => (
                  <div>
                    <form.Field name={`people[${i}].name`}>
                      {(subField) => (
                        <div>
                          <label>
                            <div>Name for person {i}</div>
                            <input
                              value={subField().state.value}
                              onInput={(e) => {
                                subField().handleChange(e.currentTarget.value)
                              }}
                            />
                          </label>
                        </div>
                      )}
                    </form.Field>
                    <button
                      onClick={() => field().removeValue(i)}
                      type="button"
                    >
                      Remove
                    </button>
                  </div>
                )}
              </Index>
            </Show>

            <button
              onClick={() => field().pushValue({ name: '', age: 0 })}
              type="button"
            >
              Add person
            </button>
          </div>
        )}
      </form.Field>
      <button type="submit">Submit</button>
    </form>
  )
}

See Also

Build docs developers (and LLMs) love