Skip to main content

Fields

Formix models form state as field references created with defineField and defineArrayField.

Scalar fields​

import { defineField } from '@ekz/formix';

const refs = {
email: defineField(''),
age: defineField(0),
};

Pass initial values when editing existing entities:

defineField(entity?.email ?? '');

Binding with useField​

const { value, setValue, error, touched, setTouched } = useField(field);

<input
value={value}
onChange={(e) => setValue(e.target.value)}
onBlur={() => setTouched(true)}
/>;

error is populated when a validator returns a message and the field is touched.

Array fields​

Dynamic lists use defineArrayField and useArrayField:

import { defineArrayField, defineField } from '@ekz/formix';
import { List } from 'immutable';

function defineItemField(item?: Item) {
return {
label: defineField(item?.label ?? ''),
};
}

const items = defineArrayField(List<ItemFieldRefs>(), defineItemField);
const { items, push, remove, move } = useArrayField(field);

items.map((itemRef, index) => (
<ItemRow key={itemRef.id} field={itemRef} onRemove={() => remove(index)} />
));

Immutable collections​

Formix works well with immutable.js Set, List, and Map as field values — especially for tags, ordered lists, and deduplication.

Field metadata​

Field refs carry stable identities across renders. Use the same ref object for useField, useFieldValidation, and getValues.

Groups and optional sub-forms​

A field's value is opaque to formix: refs stored inside a field's value are not traversed by getValues, getStates or isFieldValid. Group refs in a plain object instead, and model an optional sub-form as an array field holding zero or one item:

function defineAddress(address?: Address) {
return {
street: defineField(address?.street ?? ''),
city: defineField(address?.city ?? ''),
};
}

const refs = {
shipping: defineAddress(order.shipping),
billing: defineArrayField(order.billing != null ? [order.billing] : [], defineAddress), // optional
};

Anti-patterns​

  • Raw useState per input — loses shared valid / modified and cross-field validation
  • String keys — values.email breaks ref safety; use FieldRef instead
  • Validation in save handlers — use useFieldValidation so submit stays disabled until fixed