Перейти к основному содержимому

Схема формы

Схема формы определяет структуру данных формы и конфигурацию полей.

Тип FormSchema

FormSchema<T> автоматически отображает ваш TypeScript-интерфейс на конфигурацию полей:

import { FormSchema, GroupNode } from '@reformer/core';

interface User {
name: string;
email: string;
age: number;
}

const schema: FormSchema<User> = {
name: { value: '' },
email: { value: '' },
age: { value: 0 },
};

const form = new GroupNode<User>({ form: schema });

Правила отображения типов

FormSchema<T> использует следующие правила для определения типов полей:

Тип TypeScriptТип схемыПример
string, number, booleanFieldConfig<T>name: { value: '' }
Date, File, BlobFieldConfig<T>date: { value: null }
Вложенный объектFormSchema<T>address: { city: {...} }
Массив объектов[FormSchema<T>]items: [{ name: {...} }]
Массив примитивовFieldConfig<T[]>tags: { value: [] }

Примитивы

interface BasicForm {
name: string;
age: number;
active: boolean;
}

const schema: FormSchema<BasicForm> = {
name: { value: '' }, // FieldConfig<string>
age: { value: 0 }, // FieldConfig<number>
active: { value: false }, // FieldConfig<boolean>
};

Вложенные объекты

Объекты становятся вложенными FormSchema:

interface WithAddress {
name: string;
address: {
street: string;
city: string;
};
}

const schema: FormSchema<WithAddress> = {
name: { value: '' },
address: {
// FormSchema<Address>
street: { value: '' },
city: { value: '' },
},
};

Массивы

Массивы объектов используют синтаксис кортежа [{...}]:

interface WithItems {
title: string;
items: Array<{
name: string;
price: number;
}>;
}

const schema: FormSchema<WithItems> = {
title: { value: '' },
items: [
{
// [FormSchema<Item>]
name: { value: '' },
price: { value: 0 },
},
],
};

FieldConfig

Каждое поле использует FieldConfig<T>:

interface FieldConfig<T> {
value: T | null; // Начальное значение (обязательно)
disabled?: boolean; // Состояние «отключено»
updateOn?: 'change' | 'blur' | 'submit'; // Когда обновлять
debounce?: number; // Задержка для асинхронной валидации (мс)
}

Опции полей

const schema: FormSchema<User> = {
// Базовое поле
name: { value: '' },

// Отключено по умолчанию
email: { value: '', disabled: true },

// Обновление при blur (не при каждом нажатии клавиши)
password: { value: '', updateOn: 'blur' },

// Задержка асинхронной валидации
username: { value: '', debounce: 300 },
};

Опциональные поля

Обрабатывайте опциональные поля с помощью null:

interface Profile {
name: string;
bio?: string;
avatar?: File;
}

const schema: FormSchema<Profile> = {
name: { value: '' },
bio: { value: '' }, // Пустая строка для опциональной строки
avatar: { value: null }, // null для опционального File
};

Комплексный пример

interface Order {
customer: {
name: string;
email: string;
phone?: string;
};
items: Array<{
product: string;
quantity: number;
price: number;
}>;
shipping: {
address: string;
city: string;
notes?: string;
};
express: boolean;
}

const orderSchema: FormSchema<Order> = {
customer: {
name: { value: '' },
email: { value: '' },
phone: { value: '' },
},
items: [
{
product: { value: '' },
quantity: { value: 1 },
price: { value: 0 },
},
],
shipping: {
address: { value: '' },
city: { value: '' },
notes: { value: '' },
},
express: { value: false },
};

const form = new GroupNode<Order>({ form: orderSchema });

Вывод типов

TypeScript автоматически выводит типы:

const form = new GroupNode({
form: {
name: { value: '' },
age: { value: 0 },
},
});

// TypeScript знает:
form.value.name; // string
form.value.age; // number
form.controls.name; // FieldNode<string>
form.controls.age; // FieldNode<number>

Следующие шаги