Формы на сигналах
Signal Forms управляют состоянием форм с помощью сигналов Angular, обеспечивая автоматическую синхронизацию между моделью данных и UI.
Это руководство проводит по основным концепциям создания форм с Signal Forms. Как это работает:
Создание первой формы
1. Создайте модель формы с signal()
Каждая форма начинается с создания сигнала, хранящего модель данных формы:
interface LoginData {
email: string;
password: string;
}
const loginModel = signal<LoginData>({
email: '',
password: '',
});
2. Передайте модель формы в form(), чтобы создать FieldTree
Затем передайте модель формы в функцию form(), чтобы создать дерево полей — объектную структуру, зеркалирующую форму модели и позволяющую обращаться к полям через точечную нотацию.
И корневой объект формы, и его вложенные свойства — узлы FieldTree:
const loginForm = form(loginModel);
loginForm; // is a FieldTree
loginForm.email; // is also a FieldTree
3. Привяжите HTML-поля директивой [formField]
Далее привяжите HTML-поля к форме директивой [formField], которая создаёт двустороннюю привязку:
<input type="email" [formField]="loginForm.email" />
<input type="password" [formField]="loginForm.password" />
В результате изменения пользователя (например, ввод в поле) автоматически обновляют форму.
ПРИМЕЧАНИЕ: Директива [formField] также синхронизирует состояние поля для атрибутов вроде required, disabled и readonly, когда это уместно.
4. Читайте состояние через сигналы FieldTree
К состоянию любой части дерева можно обратиться, вызвав узел FieldTree как функцию. Это возвращает объект состояния с реактивными сигналами значения, статуса валидации и состояния взаимодействия:
loginForm(); // Returns state for the whole form
loginForm.email(); // Returns state for the email field
Чтобы прочитать текущее значение, обратитесь к сигналу value():
<!-- Render values that update automatically as user types -->
<p>Form value: {{ loginForm().value() | json }}</p>
<p>Email: {{ loginForm.email().value() }}</p>
// Get the current value
const currentEmail = loginForm.email().value();
5. Обновляйте значения через set()
Значения можно обновлять программно методом value.set() на любом узле. Это обновляет и FieldTree, и нижележащий сигнал модели:
// Update the value programmatically
loginForm.email().value.set('alice@wonderland.com');
В результате автоматически обновляются и значение поля, и сигнал модели:
// The model signal is also updated
console.log(loginModel().email); // 'alice@wonderland.com'
Полный пример
Базовое использование
Директива [formField] работает со всеми стандартными типами HTML-полей. Вот самые распространённые паттерны:
Текстовые поля
Текстовые поля работают с разными атрибутами type и textarea:
<!-- Text and email -->
<input type="text" [formField]="form.name" />
<input type="email" [formField]="form.email" />
Числа
Числовые поля автоматически преобразуют строки в числа и обратно:
<!-- Number - automatically converts to number type -->
<input type="number" [formField]="form.age" />
Дата и время
Поля даты хранят значения как строки YYYY-MM-DD, поля времени — в формате HH:mm:
<!-- Date and time - stores as ISO format strings -->
<input type="date" [formField]="form.eventDate" />
<input type="time" [formField]="form.eventTime" />
Если нужно преобразовать строки дат в объекты Date, передайте значение поля в Date():
const dateObject = new Date(form.eventDate().value());
Многострочный текст
Textarea работают так же, как текстовые поля:
<!-- Textarea -->
<textarea [formField]="form.message" rows="4"></textarea>
Чекбоксы
Чекбоксы привязываются к булевым значениям:
<!-- Single checkbox -->
<label>
<input type="checkbox" [formField]="form.agreeToTerms" />
I agree to the terms
</label>
Несколько чекбоксов
Для нескольких опций создайте отдельный булев formField для каждой:
<label>
<input type="checkbox" [formField]="form.emailNotifications" />
Email notifications
</label>
<label>
<input type="checkbox" [formField]="form.smsNotifications" />
SMS notifications
</label>
Радиокнопки
Радиокнопки работают похоже на чекбоксы. Пока радиокнопки используют одно и то же значение [formField], Signal Forms автоматически привяжет одинаковый атрибут name ко всем:
<label>
<input type="radio" value="free" [formField]="form.plan" />
Free
</label>
<label>
<input type="radio" value="premium" [formField]="form.plan" />
Premium
</label>
Когда пользователь выбирает радиокнопку, formField формы сохраняет значение из атрибута value этой радиокнопки. Например, выбор «Premium» устанавливает form.plan().value() в "premium".
Выпадающие списки select
Элементы select работают и со статическими, и с динамическими опциями:
<!-- Static options -->
<select [formField]="form.country">
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>
<!-- Dynamic options with @for -->
<select [formField]="form.productId">
<option value="">Select a product</option>
@for (product of products; track product.id) {
<option [value]="product.id">{{ product.name }}</option>
}
</select>
ПРИМЕЧАНИЕ: Множественный select (<select multiple>) сейчас не поддерживается директивой [formField].
Валидация и состояние
Signal Forms предоставляет встроенные валидаторы, которые можно применять к полям формы. Чтобы добавить валидацию, передайте функцию схемы вторым аргументом в form():
const loginForm = form(loginModel, (schemaPath) => {
debounce(schemaPath.email, 500);
required(schemaPath.email);
email(schemaPath.email);
});
Функция схемы получает параметр schema path, дающий пути к полям для настройки правил валидации.
Распространённые валидаторы:
required()— проверяет, что у поля есть значениеemail()— проверяет формат emailmin()/max()— проверяют диапазоны чиселminLength()/maxLength()— проверяют длину строки или коллекцииpattern()— проверяет по regex-шаблону
Сообщения об ошибках можно настроить, передав объект опций вторым аргументом валидатора:
required(schemaPath.email, {message: 'Email is required'});
email(schemaPath.email, {message: 'Please enter a valid email address'});
Каждый узел в FieldTree предоставляет состояние валидации и взаимодействия через реактивные сигналы.
Сигналы состояния FieldTree
Каждый узел дерева, включая корневой объект формы, предоставляет одни и те же сигналы для отслеживания состояния. Поскольку каждый узел — FieldTree, API мониторинга валидности и взаимодействия одинаков на каждом уровне.
| Состояние | Описание |
|---|---|
valid() |
Возвращает true, если узел проходит все правила валидации |
invalid() |
Возвращает true, если есть ошибки валидации |
pending() |
Возвращает true, если идёт асинхронная валидация |
touched() |
Возвращает true, если пользователь сфокусировал и снял фокус с поля или любого дочернего поля |
dirty() |
Возвращает true, если значение изменено пользователем |
disabled() |
Возвращает true, если узел отключён |
readonly() |
Возвращает true, если узел только для чтения |
errors() |
Возвращает массив ошибок валидации со свойствами kind и message |
Полный пример
Следующие шаги
Чтобы узнать больше о Signal Forms и их устройстве, см. подробные руководства:
- Обзор — введение в Signal Forms и когда их использовать
- Модели форм — создание и управление данными форм с сигналами
- Управление состоянием полей — работа с состоянием валидации, отслеживанием взаимодействия и видимостью полей
- Валидация — встроенные валидаторы, пользовательские правила и асинхронная валидация