.md

disabled

useForm({ disabled }) freezes a reactive form so its data cannot be edited, and nothing can write around the freeze. The guarantee lives at the data layer, so a stray binding, a programmatic write, and a host component all no-op at once. Read-only review screens and hard-prerequisite steps lean on it.

Category
Form option
Signature
useForm({ disabled })
Accepts
boolean · ref · computed · getter
Reads back
form.meta.disabled · field.disabled

Flip the toggle and every input freezes together. You never wrote :disabled on a single one of them: Attaform sets the native attribute on each control from that one option, and the greyed, not-allowed look is plain input:disabled CSS.

{"fullName":"Ada Lovelace","email":"ada@example.com","role":"engineer"}

Flip disabled and every input freezes at once. Attaform sets the native disabled attribute on each control, so the greyed, not-allowed look is plain input:disabled CSS with nothing wired per field. The freeze reaches the data layer too: typing while frozen leaves form.values untouched.

One option, every write

disabled accepts a boolean, a ref, a computed, or a getter (MaybeRefOrGetter<boolean>), unwrapped live so a reactive source keeps tracking:

import { ref } from 'vue'
import { useForm } from 'attaform'
import { z } from 'zod'

const frozen = ref(false)

const profileSchema = z.object({
  fullName: z.string().min(1),
  email: z.email(),
})

const form = useForm({
  schema: profileSchema,
  disabled: frozen,
})

While disabled resolves truthy:

  • Every value write no-ops at Attaform's single write chokepoint, so the programmatic, v-register, and host-model paths all fall inert together. The freeze is enforced in the data, not on the inputs, so a deep link or a rogue write cannot slip past it.
  • Native inputs render the HTML disabled attribute on the server and the client, component hosts and native selects receive a :disabled bind, and every field's display state settles to idle, so no error, pending, or success signal shows on a frozen field.
  • reset() and defaultValues still hydrate. A frozen form can be seeded or restored, which is exactly what a read-only review screen needs.

The resolved state reads back on form.meta.disabled and field.disabled, both read-only, so a template can style the frozen state without tracking the flag itself.

Gating a wizard step

gate(step) drives this same freeze for a hard prerequisite: every step after an uncleared gate is frozen through disabled, so it is un-fillable as well as unreachable, and a cleared gate's own form freezes too. See gate for the full model.