Form

@domphy/form provides headless form state for Domphy apps: typed values, per-field and form-level validators (sync + async), touched/blurred/dirty tracking, arrays, and Standard Schema support.

It is a 1-1 port of @tanstack/form-core v1.33.0 (MIT, © Tanner Linsley and the TanStack team). The src/ is byte-identical to upstream, so the entire TanStack Form reference applies as-is. The only addition is the Domphy adapter in src/domphy/.

It replaces the ad-hoc FormState / FieldState that used to live in @domphy/ui, so form logic lives in exactly one place.

Install

<div class="blocks">
<div class="block active" data-tab="0">
npm install @domphy/form @domphy/core
</div>
<div class="block" data-tab="1">

</div>
</div>

@domphy/core is a peer dependency of the adapter only.

Live Example

Adapter

createForm(options) (from @domphy/form/domphy) owns the form; form.field(name, options?) binds one input.

import { createForm } from "@domphy/form/domphy"

const form = createForm<{ email: string }>({
  defaultValues: { email: "" },
  onSubmit: ({ value }) => save(value),
})

const email = form.field<string>("email", {
  validators: { onChange: ({ value }) => (value.includes("@") ? undefined : "Invalid email") },
})

Bind a field to a native input — read value/errors reactively, forward DOM events to the handle:

import { inputText, label, formGroup } from "@domphy/ui"

const Field = {
  div: [
    { label: "Email", $: [label()] },
    {
      input: null,
      $: [inputText()],
      value: (l) => email.value(l),
      onInput: (e) => email.handleChange((e.target as HTMLInputElement).value),
      onBlur: () => email.handleBlur(),
    },
    {
      div: (l) => String(email.errors(l)[0] ?? ""),
      hidden: (l) => email.errors(l).length === 0,
    },
  ],
  $: [formGroup()],
}

Form handle

MemberDescription
values(l) / state(l)Reactive form values / full form state.
canSubmit(l) / isSubmitting(l) / isValid(l) / isSubmitted(l)Reactive flags.
field<TData>(name, options?)Create and mount a reactive field handle.
handleSubmit()Run validation and submission.
reset(values?)Reset to defaults (or given values).
formThe underlying FormApi.
destroy()Unmount the form and all fields; call from _onRemove.

Field handle

MemberDescription
value(l)Reactive value — bind to the input's value/checked.
errors(l) / meta(l)Reactive validation errors / full field meta.
handleChange(value)Update the value (from onInput/onChange).
handleBlur()Mark blurred and run blur validators.
setValue(updater)Set the value programmatically.
apiThe underlying FieldApi.

Field and form options (validators, async debouncing, listeners, arrays, Standard Schema) are the upstream form-core options — see the TanStack Form docs.