Ноды и proxy
Ноды — строительные блоки формы. Их не создают вручную через new — их строит createForm
поверх сигналов модели, а доступ к ним даёт типизированный proxy.
| Нода | Назначение | Пример |
|---|---|---|
FieldNode | одно значение (строка, число, флаг) | текстовое поле, чекбокс |
GroupNode | объект с именованными полями | секция формы, адрес |
ArrayNode | динамический список подформ | телефоны, адреса |
ModelArrayNode | массив, привязанный к массиву модели | список объектов модели |
Доступ через proxy
createForm возвращает proxy: к полям обращаются по имени, вложенность — цепочкой.
import { createModel, createForm } from '@reformer/core';
import { Input } from '@reformer/ui-kit';
type Form = { firstName: string; address: { city: string } };
const model = createModel<Form>({ firstName: '', address: { city: '' } });
const schema = {
firstName: { value: model.$.firstName, component: Input },
address: {
city: { value: model.$.address.city, component: Input },
},
};
const form = createForm<Form>({ model, schema });
form.firstName; // FieldNode<string>
form.address; // GroupNode
form.address.city; // FieldNode<string> — вложенный доступ
instanceofНе проверяйте тип ноды через node instanceof FieldNode — proxy это не пройдёт. Используйте
type-guards.
Состояние ноды — сигналы
Свойства ноды value, valid, invalid, errors, touched, dirty, disabled, pending —
сигналы (реактивные, только для чтения). В React их удобнее читать через
useFormControl; вне React — через методы ниже или .value сигнала.
| Свойство (сигнал) | Тип | Описание |
|---|---|---|
value | T | текущее значение |
valid / invalid | boolean | проходит / не проходит валидацию |
errors | ValidationError[] | ошибки валидации ([] когда валидно) |
touched / dirty | boolean | пользователь взаимодействовал / значение менялось |
disabled | boolean | поле отключено |
pending | boolean | идёт асинхронная валидация |
Методы ноды
form.firstName.getValue(); // прочитать значение
form.firstName.setValue('John'); // записать значение
form.firstName.patchValue(partial); // частичное обновление (для групп/массивов)
form.firstName.reset(); // сброс к начальному
form.firstName.markAsTouched(); // отметить как «тронутое»
form.firstName.markAsDirty();
form.firstName.disable(); // отключить
form.firstName.enable(); // включить
form.firstName.validate(); // запустить валидацию ноды
Изменение значения через ноду отражается в модели (и наоборот) — это одни и те же сигналы.
FieldNode
Лист дерева. Дополнительно к общим методам:
form.email.updateComponentProps({ options: [...] }); // обновить пропсы компонента (например, опции Select)
form.email.componentProps; // сигнал текущих componentProps
form.email.shouldShowError; // сигнал: показывать ли ошибку (touched + invalid)
GroupNode
Группирует поля в объект.
form.address.getValue(); // { city: '...', zip: '...' }
form.address.touchAll(); // отметить все дочерние поля тронутыми
form.address.getFieldByPath('city'); // доступ по строковому пути
ArrayNode
Динамический список подформ. Сами данные принадлежат модели, поэтому мутации выполняются на модели, а нода отражает их реактивно:
model.phones.push({ type: 'mobile', number: '' }); // добавить элемент
model.phones.removeAt(0); // удалить
form.phones.at(0); // FormProxy элемента
form.phones.map((item, i) => /* ... */); // обход элементов
Type-guards
Поскольку proxy не проходит instanceof, тип ноды определяют через guard-функции:
import { isFieldNode, isGroupNode, isArrayNode, getNodeType } from '@reformer/core';
if (isFieldNode(node)) {
/* лист */
}
if (isGroupNode(node)) {
/* группа */
}
if (isArrayNode(node)) {
/* массив */
}
getNodeType(node); // 'field' | 'group' | 'array'
Дальше
- Схема формы — как описать структуру и привязать ноды к модели.
- React-хуки — читать состояние нод в компонентах.
- Массивы и динамические формы — работа с
ArrayNodeна практике.