Field Model
A field is the smallest model unit in Virentia Forms. Use it when a single value needs behavior around it: changing, resetting, validation, focus state, metadata, or server errors.
A field can live inside a form, inside another field, or by itself. That is the important boundary: a field is not an input component; it is a model for one piece of form state.
Basic Field
ts
import { createField } from "@virentia/forms";
const title = createField("");
await title.fill("Virentia");
title.read(); // "Virentia"
title.state.value; // "Virentia"What happens:
stateis a Virentia store;fillwrites a new value and emitschanged;readreturns the value in the current scope;resetrestores the initial value, initial errors, focus state, and metadata.
Validation On A Field
ts
const username = createField("", {
validate(value) {
return value.trim().length >= 3 ? null : "Use at least 3 characters";
},
});
await username.validate();
username.error.value; // "Use at least 3 characters"
username.isValid.value; // falseField validation is for rules that only need one value. If the rule compares several fields, put it on the form model.
Metadata And Focus
Use meta for state that belongs to the field but should not become part of the submitted value.
ts
const price = createField(0, {
meta: {
touchedByUser: false,
},
});
await price.changeMeta({ touchedByUser: true });
await price.focus();
await price.blur();Common metadata examples:
- UI mode for a domain field;
- source of the latest change;
- flag that a value was normalized manually;
- per-field view hints.
Contract
ts
function createField<Value, Meta extends object = Record<string, never>>(
initial: Value,
options?: {
error?: FieldError;
meta?: Meta;
validate?: FieldValidator<Value> | readonly FieldValidator<Value>[];
validationStrategies?: readonly ValidationStrategy[];
},
): Field<Value, Meta>;
interface Field<Value, Meta extends object = Record<string, never>>
extends NormalizedField<Value, FieldError, Value> {
readonly error: Store<FieldError>;
readonly innerError: Store<FieldError>;
readonly outerError: Store<FieldError>;
readonly meta: Store<Meta>;
readonly isFocused: Store<boolean>;
fill(value: Value): Promise<void>;
reset(): Promise<void>;
validate(): Promise<void>;
focus(): Promise<void>;
blur(): Promise<void>;
changeMeta(meta: Meta): Promise<void>;
}Common Cases
Use a primitive field for:
- text, number, checkbox, select, and date values;
- search filters that need validation or reset;
- local models that later may become part of a form;
- fields reused by several screens;
- simple values inside shape fields and array fields.
Related
- Form model - how fields become one payload.
- Validation lifecycle - how validators run.
- Error channels - why field errors have two layers.
- Custom fields - how several fields expose one value.