GroupNode
Defined in: core/nodes/group-node.ts:82
GroupNode - узел для группы полей
Поддерживает два API:
- Старый API (только schema) - обратная совместимость
- Новый API (config с form, behavior, validation) - автоматическое применение схем
Example
// 1. Старый способ (обратная совместимость)
const simpleForm = new GroupNode({
email: { value: '', component: Input },
password: { value: '', component: Input },
});
// 2. Новый способ (с behavior и validation схемами)
const fullForm = new GroupNode({
form: {
email: { value: '', component: Input },
password: { value: '', component: Input },
},
behavior: (path) => {
computeFrom(path.email, [path.email], (values) => values[0]?.trim());
},
validation: (path) => {
required(path.email, { message: 'Email обязателен' });
email(path.email);
required(path.password);
minLength(path.password, 8);
},
});
// Прямой доступ к полям через Proxy
fullForm.email.setValue('test@mail.com');
await fullForm.validate();
console.log(fullForm.valid.value); // true
Extends
FormNode<T>
Type Parameters
T
T
Accessors
fields
Get Signature
get fields(): FieldRegistry<T>;
Defined in: core/nodes/group-node.ts:427
Получить Map всех полей формы
Используется в FieldPathNavigator для навигации по полям
Returns
FieldRegistry<T>
Map полей формы
Constructors
Constructor
new GroupNode<T>(schema): GroupNode<T>;
Defined in: core/nodes/group-node.ts:180
Создать GroupNode только со схемой формы (обратная совместимость)
Parameters
schema
FormSchema<T>
Returns
GroupNode<T>
Overrides
Constructor
new GroupNode<T>(config): GroupNode<T>;
Defined in: core/nodes/group-node.ts:185
Создать GroupNode с полной конфигурацией (form, behavior, validation)
Parameters
config
Returns
GroupNode<T>
Overrides
FormNode<T>.constructor
Methods
applyBehaviorSchema()
applyBehaviorSchema(schemaFn): () => void;
Defined in: core/nodes/group-node.ts:604
Применить behavior schema к форме
✅ РЕФАКТОРИНГ: Делегирование BehaviorApplicator (SRP)
Логика применения behavior схемы извлечена в BehaviorApplicator для:
- Соблюдения Single Responsibility Principle
- Уменьшения размера GroupNode (~50 строк)
- Улучшения тестируемости
- Консистентности с ValidationApplicator
Parameters
schemaFn
Функция описания поведения формы
Returns
Функция cleanup для отписки от всех behaviors
(): void;
Returns
void
Example
import { copyFrom, enableWhen, computeFrom } from '@/lib/forms/core/behaviors';
const behaviorSchema: BehaviorSchemaFn<MyForm> = (path) => {
copyFrom(path.residenceAddress, path.registrationAddress, {
when: (form) => form.sameAsRegistration === true
});
enableWhen(path.propertyValue, (form) => form.loanType === 'mortgage');
computeFrom(
path.initialPayment,
[path.propertyValue],
(propertyValue) => propertyValue ? propertyValue * 0.2 : null
);
};
const cleanup = form.applyBehaviorSchema(behaviorSchema);
// Cleanup при unmount
useEffect(() => cleanup, []);
applyContextualValidators()
applyContextualValidators(validators): Promise<void>;
Defined in: core/nodes/group-node.ts:694
Применить contextual валидаторы к полям
✅ РЕФАКТОРИНГ: Делегирование ValidationApplicator (SRP)
Логика применения валидаторов извлечена в ValidationApplicator для:
- Соблюдения Single Responsibility Principle
- Уменьшения размера GroupNode (~120 строк)
- Улучшения тестируемости
Parameters
validators
ValidatorRegistration[]
Зарегистрированные валидаторы
Returns
Promise<void>
applyValidationSchema()
applyValidationSchema(schemaFn): void;
Defined in: core/nodes/group-node.ts:551
Применить validation schema к форме
Использует локальный реестр валидаторов (this.validationRegistry) вместо глобального Singleton для изоляции форм друг от друга.
Parameters
schemaFn
Returns
void
clearErrors()
clearErrors(): void;
Defined in: core/nodes/group-node.ts:392
Очистить все errors (form-level + field-level)
Returns
void
Overrides
disable()
disable(): void;
Defined in: core/nodes/form-node.ts:370
Отключить узел
Template Method: обновляет статус в базовом классе, вызывает hook для кастомной логики в наследниках
Отключенные узлы не проходят валидацию и не включаются в getValue()
Returns
void
Inherited from
dispose()
dispose(): void;
Defined in: core/nodes/group-node.ts:876
Очистить все ресурсы узла Рекурсивно очищает все subscriptions и дочерние узлы
Returns
void
Example
useEffect(() => {
return () => {
form.dispose();
};
}, []);
Overrides
enable()
enable(): void;
Defined in: core/nodes/form-node.ts:381
Включить узел
Template Method: обновляет статус в базовом классе, вызывает hook для кастомной логики в наследниках
Returns
void
Inherited from
getAllFields()
getAllFields(): IterableIterator<FormNode<FormValue>>;
Defined in: core/nodes/group-node.ts:476
Получить все поля формы как итератор
Предоставляет доступ к внутренним полям для валидации и других операций
Returns
IterableIterator<FormNode<FormValue>>
Итератор по всем полям формы
Example
// Валидация всех полей
await Promise.all(
Array.from(form.getAllFields()).map(field => field.validate())
);
getErrors()
getErrors(options?): ValidationError[];
Defined in: core/nodes/form-node.ts:231
Получить ошибки валидации с фильтрацией
Позволяет фильтровать ошибки по различным критериям:
- По коду ошибки
- По сообщению (частичное совпадение)
- По параметрам
- Через кастомный предикат
Без параметров возвращает все ошибки (эквивалент errors.value)
Parameters
options?
Опции фильтрации ошибок
Returns
Отфильтрованный массив ошибок валидации
Example
// Все ошибки
const allErrors = form.getErrors();
// Ошибки с конкретным кодом
const requiredErrors = form.getErrors({ code: 'required' });
// Ошибки с несколькими кодами
const errors = form.getErrors({ code: ['required', 'email'] });
// Ошибки по сообщению
const passwordErrors = form.getErrors({ message: 'Password' });
// Ошибки по параметрам
const minLengthErrors = form.getErrors({
params: { minLength: 8 }
});
// Кастомная фильтрация
const customErrors = form.getErrors({
predicate: (err) => err.code.startsWith('custom_')
});
Inherited from
getField()
getField<K>(key): FormNode<T[K]> | undefined;
Defined in: core/nodes/group-node.ts:416
Получить поле по ключу
Публичный метод для доступа к полю из fieldRegistry
Type Parameters
K
K extends string | number | symbol
Parameters
key
K
Ключ поля
Returns
FormNode<T[K]> | undefined
FormNode или undefined, если поле не найдено
Example
const emailField = form.getField('email');
if (emailField) {
console.log(emailField.value.value);
}
getFieldByPath()
getFieldByPath(path):
| FormNode<FormValue>
| undefined;
Defined in: core/nodes/group-node.ts:637
Получить вложенное поле по пути
Поддерживаемые форматы путей:
- Simple: "email" - получить поле верхнего уровня
- Nested: "address.city" - получить вложенное поле
- Array index: "items[0]" - получить элемент массива по индексу
- Combined: "items[0].name" - получить поле элемента массива
Parameters
path
string
Путь к полю
Returns
| FormNode<FormValue>
| undefined
FormNode если найдено, undefined если путь не существует
Example
const form = new GroupNode({
email: { value: '', component: Input },
address: {
city: { value: '', component: Input }
},
items: [{ name: { value: '', component: Input } }]
});
form.getFieldByPath('email'); // FieldNode
form.getFieldByPath('address.city'); // FieldNode
form.getFieldByPath('items[0]'); // GroupNode
form.getFieldByPath('items[0].name'); // FieldNode
form.getFieldByPath('invalid.path'); // undefined
getProxy()
getProxy(): any;
Defined in: core/nodes/group-node.ts:457
Получить Proxy-инстанс для прямого доступа к полям
Proxy позволяет обращаться к полям формы напрямую через точечную нотацию:
- form.email вместо form.fields.get('email')
- form.address.city вместо form.fields.get('address').fields.get('city')
Используется в:
- BehaviorApplicator для доступа к полям в behavior functions
- ValidationApplicator для доступа к форме в tree validators
Returns
any
Proxy-инстанс с типобезопасным доступом к полям или сама форма, если proxy не доступен
Example
const form = new GroupNode({
controls: {
email: new FieldNode({ value: '' }),
name: new FieldNode({ value: '' })
}
});
const proxy = form.getProxy();
console.log(proxy.email.value); // Прямой доступ к полю
getValue()
getValue(): T;
Defined in: core/nodes/group-node.ts:252
Получить значение узла (non-reactive) Использует .peek() для получения значения без создания зависимости
Returns
T
Overrides
linkFields()
linkFields<K1, K2>(
sourceKey,
targetKey,
transform?): () => void;
Defined in: core/nodes/group-node.ts:753
Связывает два поля: при изменении source автоматически обновляется target Поддерживает опциональную трансформацию значения
Type Parameters
K1
K1 extends string | number | symbol
K2
K2 extends string | number | symbol
Parameters
sourceKey
K1
Ключ поля-источника
targetKey
K2
Ключ поля-цели
transform?
(value) => T[K2]
Опциональная функция трансформации значения
Returns
Функция отписки для cleanup
(): void;
Returns
void
Example
// Автоматический расчет минимального взноса от стоимости недвижимости
const dispose = form.linkFields(
'propertyValue',
'initialPayment',
(propertyValue) => propertyValue ? propertyValue * 0.2 : null
);
// При изменении propertyValue → автоматически обновится initialPayment
form.propertyValue.setValue(1000000);
// initialPayment станет 200000
// Cleanup
useEffect(() => dispose, []);
markAsDirty()
markAsDirty(): void;
Defined in: core/nodes/form-node.ts:313
Отметить узел как dirty (значение изменено)
Template Method: обновляет signal в базовом классе, вызывает hook для кастомной логики в наследниках
Returns
void
Inherited from
markAsPristine()
markAsPristine(): void;
Defined in: core/nodes/form-node.ts:324
Отметить узел как pristine (значение не изменено)
Template Method: обновляет signal в базовом классе, вызывает hook для кастомной логики в наследниках
Returns
void
Inherited from
markAsTouched()
markAsTouched(): void;
Defined in: core/nodes/form-node.ts:291
Отметить узел как touched (пользователь взаимодействовал)
Template Method: обновляет signal в базовом классе, вызывает hook для кастомной логики в наследниках
Returns
void
Inherited from
markAsUntouched()
markAsUntouched(): void;
Defined in: core/nodes/form-node.ts:302
Отметить узел как untouched
Template Method: обновляет signal в базовом классе, вызывает hook для кастомной логики в наследниках
Returns
void
Inherited from
onDisable()
protected onDisable(): void;
Defined in: core/nodes/group-node.ts:840
Hook: вызывается после disable()
Для GroupNode: рекурсивно отключаем все дочерние поля
Returns
void
Overrides
onEnable()
protected onEnable(): void;
Defined in: core/nodes/group-node.ts:854
Hook: вызывается после enable()
Для GroupNode: рекурсивно включаем все дочерние поля
Returns
void
Overrides
onMarkAsDirty()
protected onMarkAsDirty(): void;
Defined in: core/nodes/group-node.ts:507
Hook: вызывается после markAsDirty()
Для GroupNode: рекурсивно помечаем все дочерние поля как dirty
Returns
void
Overrides
onMarkAsPristine()
protected onMarkAsPristine(): void;
Defined in: core/nodes/group-node.ts:516
Hook: вызывается после markAsPristine()
Для GroupNode: рекурсивно помечаем все дочерние поля как pristine
Returns
void
Overrides
onMarkAsTouched()
protected onMarkAsTouched(): void;
Defined in: core/nodes/group-node.ts:489
Hook: вызывается после markAsTouched()
Для GroupNode: рекурсивно помечаем все дочерние поля как touched
Returns
void
Overrides
onMarkAsUntouched()
protected onMarkAsUntouched(): void;
Defined in: core/nodes/group-node.ts:498
Hook: вызывается после markAsUntouched()
Для GroupNode: рекурсивно помечаем все дочерние поля как untouched
Returns
void
Overrides
patchValue()
patchValue(value): void;
Defined in: core/nodes/group-node.ts:272
Частично обновить значение узла Для FieldNode: работает как setValue Для GroupNode: обновляет только указанные поля Для ArrayNode: обновляет только указанные элементы
Parameters
value
Partial<T>
частичное значение для обновления
Returns
void
Overrides
reset()
reset(value?): void;
Defined in: core/nodes/group-node.ts:304
Сбросить форму к указанным значениям (или к initialValues)
Parameters
value?
T
опциональный объект со значениями для сброса
Returns
void
Remarks
Рекурсивно вызывает reset() для всех полей формы
Example
// Сброс к initialValues
form.reset();
// Сброс к новым значениям
form.reset({ email: 'new@mail.com', password: '' });
Overrides
resetToInitial()
resetToInitial(): void;
Defined in: core/nodes/group-node.ts:339
Сбросить форму к исходным значениям (initialValues)
Returns
void
Remarks
Рекурсивно вызывает resetToInitial() для всех полей формы. Более явный способ сброса к начальным значениям по сравнению с reset()
Полезно когда:
- Пользователь нажал "Cancel" - полная отмена изменений
- Форма была изменена через reset(newValues), но нужно вернуться к самому началу
- Явное намерение показать "отмена всех изменений"
Example
const form = new GroupNode({
email: { value: 'initial@mail.com', component: Input },
name: { value: 'John', component: Input }
});
form.email.setValue('changed@mail.com');
form.reset({ email: 'temp@mail.com', name: 'Jane' });
console.log(form.getValue()); // { email: 'temp@mail.com', name: 'Jane' }
form.resetToInitial();
console.log(form.getValue()); // { email: 'initial@mail.com', name: 'John' }
setErrors()
setErrors(errors): void;
Defined in: core/nodes/group-node.ts:385
Установить form-level validation errors Используется для server-side validation или кросс-полевых ошибок
Parameters
errors
массив ошибок уровня формы
Returns
void
Example
// Server-side validation после submit
try {
await api.createUser(form.getValue());
} catch (error) {
form.setErrors([
{ code: 'duplicate_email', message: 'Email уже используется' }
]);
}
Overrides
setValue()
setValue(value, options?): void;
Defined in: core/nodes/group-node.ts:261
Установить значение узла
Parameters
value
T
новое значение
options?
опции установки значения
Returns
void
Overrides
submit()
submit<R>(onSubmit): Promise<R | null>;
Defined in: core/nodes/group-node.ts:528
Отправить форму Валидирует форму и вызывает onSubmit если форма валидна
Type Parameters
R
R
Parameters
onSubmit
(values) => R | Promise<R>
Returns
Promise<R | null>
touchAll()
touchAll(): void;
Defined in: core/nodes/form-node.ts:354
Пометить все поля (включая вложенные) как touched Алиас для markAsTouched(), но более явно показывает намерение пометить ВСЕ поля рекурсивно
Полезно для:
- Показа всех ошибок валидации перед submit
- Принудительного отображения ошибок при нажатии "Validate All"
- Отображения невалидных полей в wizard/step form
Returns
void
Example
// Показать все ошибки перед submit
form.touchAll();
const isValid = await form.validate();
if (!isValid) {
// Все ошибки теперь видны пользователю
}
// Или использовать submit() который уже вызывает touchAll
await form.submit(async (values) => {
await api.save(values);
});
Inherited from
validate()
validate(): Promise<boolean>;
Defined in: core/nodes/group-node.ts:349
Запустить валидацию узла
Returns
Promise<boolean>
Promise<boolean> - true если валидация успешна
Overrides
watchField()
watchField<K>(fieldPath, callback): () => void;
Defined in: core/nodes/group-node.ts:811
Подписка на изменения вложенного поля по строковому пути Поддерживает вложенные пути типа "address.city"
Type Parameters
K
K extends string | number | symbol
Parameters
fieldPath
K extends string ? K<K> : string
Строковый путь к полю (например, "address.city")
callback
(value) => void | Promise<void>
Функция, вызываемая при изменении поля
Returns
Функция отписки для cleanup
(): void;
Returns
void
Example
// Подписка на изменение страны для загрузки городов
const dispose = form.watchField(
'registrationAddress.country',
async (countryCode) => {
if (countryCode) {
const cities = await fetchCitiesByCountry(countryCode);
form.registrationAddress.city.updateComponentProps({
options: cities
});
}
}
);
// Cleanup
useEffect(() => dispose, []);
Properties
_dirty
protected _dirty: Signal<boolean>;
Defined in: core/nodes/form-node.ts:56
Значение узла было изменено (dirty) Protected: наследники могут читать/изменять через методы
Inherited from
_status
protected _status: Signal<FieldStatus>;
Defined in: core/nodes/form-node.ts:62
Текущий статус узла Protected: наследники могут читать/изменять через методы
Inherited from
_touched
protected _touched: Signal<boolean>;
Defined in: core/nodes/form-node.ts:50
Пользователь взаимодействовал с узлом (touched) Protected: наследники могут читать/изменять через методы
Inherited from
dirty
readonly dirty: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:167
Значение узла было изменено (dirty) Computed из _dirty для предоставления readonly интерфейса
Overrides
disabled
readonly disabled: ReadonlySignal<boolean>;
Defined in: core/nodes/form-node.ts:99
Узел отключен (disabled)
Inherited from
enabled
readonly enabled: ReadonlySignal<boolean>;
Defined in: core/nodes/form-node.ts:104
Узел включен (enabled)
Inherited from
errors
readonly errors: ReadonlySignal<ValidationError[]>;
Defined in: core/nodes/group-node.ts:169
Массив ошибок валидации
Overrides
id
id: string;
Defined in: core/nodes/group-node.ts:86
invalid
readonly invalid: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:165
Узел невалиден (есть ошибки валидации)
Overrides
pending
readonly pending: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:168
Выполняется асинхронная валидация
Overrides
pristine
readonly pristine: ReadonlySignal<boolean>;
Defined in: core/nodes/form-node.ts:88
Значение узла не было изменено (pristine)
Inherited from
status
readonly status: ReadonlySignal<FieldStatus>;
Defined in: core/nodes/group-node.ts:170
Текущий статус узла Computed из _status для предоставления readonly интерфейса
Overrides
submitting
readonly submitting: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:171
touched
readonly touched: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:166
Пользователь взаимодействовал с узлом (touched) Computed из _touched для предоставления readonly интерфейса
Overrides
untouched
readonly untouched: ReadonlySignal<boolean>;
Defined in: core/nodes/form-node.ts:77
Пользователь не взаимодействовал с узлом (untouched)
Inherited from
valid
readonly valid: ReadonlySignal<boolean>;
Defined in: core/nodes/group-node.ts:164
Узел валиден (все валидаторы прошли успешно)
Overrides
value
readonly value: ReadonlySignal<T>;
Defined in: core/nodes/group-node.ts:163
Текущее значение узла
- Для FieldNode: значение поля
- Для GroupNode: объект со значениями всех полей
- Для ArrayNode: массив значений элементов