Skip to main content
The Form.* components bind Anvil2 input fields to a formstate field state, removing the boilerplate of wiring value, change, error, and warning props by hand. Each wrapper is a MobX observer, so it re-renders when its bound A2InputFieldState changes.
Changed in 0.9.0: Selection fields now require selectable field states and changed how they store values. See the migration guide.

Installation

Form fields rely on formstate, mobx, and mobx-react as peer dependencies. Install them alongside the package:

Usage

Create an A2InputFieldState, then pass it to the matching Form.* component. The wrapper reads value, reports validation error/warning, and writes changes back to the field state.
The field state is the source of truth. Read name.value to get the current value, call name.validate() to run validation, and check name.hasError / name.error to inspect the result. See Field state for the full API.

Owning field states from a screen store

Form.* components are binding wrappers, not a form-state framework. For a screen with more than one field, create a MobX class that owns every field state as a class property, plus an aggregate formstate.FormState for one-shot validation. Instantiate the store once per component with useState(() => new Store()) and render it with an observer component that binds fields and stays presentational:
This mirrors the store pattern used throughout the monolith app: the store owns state and mutations, the component only renders and binds.

Available wrappers

Each wrapper accepts a fieldState prop plus the underlying Anvil2 component’s props. The field state’s value type matches the field: Form.IntervalFrequency pairs a numeric interval with a frequency select and binds to a combined IntervalFrequencyFormState rather than a single field state — see Interval frequency.

Selection fields

Form.Select, Form.MultiSelect, and Form.TreeSelect wrap the beta Anvil2 select components and ship from the package root alongside the rest of the namespace. Both bind to a SelectableOptionsFieldState (Form.Select) or SelectableOptionsArrayFieldState (Form.MultiSelect), and never read that field state’s options — provide a loadOptions function instead, and bind the selected option(s) to the field state:
Form.Select and Form.MultiSelect support every loader mode. Match the loadOptions signature to the lazy prop: "page" and "offset" only support flat option lists. Use "group" when options need groupToString/groupSorter. If you need Form.SelectSync or Form.MultiSelectSync instead — the full option set is available client-side — call fieldState.setOptions() rather than passing an options prop.

Group fields

Checkbox and radio inputs are provided as the group wrappers Form.RadioGroup and Form.CheckboxGroup. These render an Anvil2 group with a FieldMessage, so validation errors and warnings surface as text. Pass an items array; the field state holds the selected option object (Form.RadioGroup) or option objects (Form.CheckboxGroup), not a bare id.

Limitations

  • Single checkbox and radio inputs have no standalone wrapper. Use Form.CheckboxGroup or Form.RadioGroup — a bare Anvil2 Checkbox/Radio exposes a boolean error (styling only) with no message area, so the group is the form pattern that renders validation messages.
  • The following Anvil2 input types have no Form.* wrapper: SearchField, InputMask, Switch, ButtonToggle, SelectCard, Combobox, SegmentedControl, and RichTextEditor.
Last modified on October 12, 2026