Angular

Signal Forms

В реактивных формах модель и её данные живут раздельно: есть объект состояния и параллельное дерево FormControl, которые приходится синхронизировать. Signal Forms убирают этот дубль. Разработчик объявляет один writable-сигнал с данными, оборачивает его в form(), и форма становится прямым реактивным отражением модели. В Angular 22 (июнь 2026) этот API стал стабильным, после экспериментального статуса в 21 и задаёт направление для нового кода.

  • Формы поверх сигнального store: модель и форма используют один источник истины
  • Сложные мастера: производные поля через computed без ручной синхронизации
  • Zoneless-приложения: формы на сигналах естественно вписываются в реактивность без зон
  • Динамические схемы: правила валидации описываются декларативно в одной schema-функции
  • Совместное состояние: один сигнал данных читается и формой, и остальным UI без копирования

Предварительные знания

  • Реактивные формы: FormGroup, FormControl, валидаторы и их ограничения
  • Сигналы: signal, computed, writable vs readonly, основы реактивности
  • Строгий TypeScript: интерфейсы, дженерики, отсутствие any и явных кастов

Третья модель форм на сигналах

После того как сигналы стали основой реактивности Angular (v16-v19), команда начала проектировать формы прямо на них. Signal Forms прошли путь от экспериментального предложения до стабильного релиза в Angular 22 (июнь 2026). Ключевая идея: форма - это не отдельное дерево объектов, а реактивная обёртка над сигналом с данными. Состояние модели и состояние формы перестают расходиться. Реактивные формы при этом не исчезают: они остаются для существующего кода, а Signal Forms становятся рекомендованным выбором для нового.

Модель: сигнал данных и form()

Signal Form начинается с writable-сигнала, хранящего данные формы как обычный объект. Функция form() оборачивает этот сигнал и возвращает дерево полей, повторяющее структуру объекта. Источник истины один: меняется сигнал - меняется форма, и наоборот.

Тип ProfileModel задаёт форму данных, и form() выводит структуру полей из него. Никаких any и явных кастов: дерево полей типизировано на основе модели, поэтому обращение к несуществующему полю - ошибка компиляции, а не рантайма.

Директива Control связывает поле формы с элементом ввода в обе стороны. В отличие от formControlName, имя поля не задаётся строкой: профиль дерева полей берётся напрямую из типизированной модели, что исключает опечатки в именах.

Что именно принимает функция form() в Signal Forms?

Поля как сигналы состояния

Каждый узел дерева полей - функция-аксессор. Её вызов возвращает объект со state-сигналами поля: value, valid, errors, touched, dirty. Это значит, что состояние формы читается реактивно прямо в шаблоне через computed и слежение за сигналами, без подписок.

Вызов profileForm.name() даёт состояние поля name. Все его свойства - сигналы, поэтому computed автоматически пересчитывается при изменении value, touched или errors. Ошибка показывается только после touched, как и в других подходах, но без ручной подписки.

Поскольку состояние поля это сигналы, оно прозрачно встраивается в zoneless change detection. Шаблон перерисовывает только то, что зависит от изменившегося сигнала, без обхода всего дерева компонентов.

Что возвращает вызов аксессора поля, например profileForm.name()?

Schema валидации и отличие от реактивных форм

Валидация в Signal Forms описывается декларативно в schema-функции, которую form() принимает вторым аргументом. Внутри schema правила вроде required, email и validate навешиваются на конкретные поля через путь к ним. Отдельного массива валидаторов на каждом контроле, как в реактивных формах, больше нет.

Колбэк validate получает контекст с сигналом value и возвращает либо null (поле валидно), либо объект ошибки. Это типобезопасно: ctx.value() имеет тип number для поля age, поэтому сравнение с 18 проверяется компилятором без какого-либо приведения типов.

  • Reactive forms — Модель данных и дерево FormControl отдельны и синхронизируются. Состояние - через Observable valueChanges. Валидаторы - массив на каждом контроле
  • Signal Forms — Один сигнал данных как источник истины, дерево полей выводится из него. Состояние - через сигналы. Валидация - декларативная schema

Signal Forms и реактивные формы решают одну задачу разными средствами. Смешивать их в одной форме не нужно. Для нового кода в Angular 22 команда рекомендует Signal Forms, существующие реактивные формы переписывать ради переписывания не требуется.

Чем модель состояния Signal Forms принципиально отличается от реактивных форм?

Связь с другими темами

Signal Forms - третья и самая новая модель форм, выросшая из сигналов:

  • Reactive forms — Предшественник: те же идеи валидации и структуры, но на Observable и отдельном дереве контролов
  • Сигналы — Фундамент: form() оборачивает writable-сигнал, а производные поля - это computed

Итог

  • Signal Forms стабильны в Angular 22 (экспериментальны в 21) и строят форму как реактивную обёртку над сигналом с данными
  • Функция form() принимает writable-сигнал модели и возвращает дерево полей, отражающее её структуру
  • Каждое поле - функция-аксессор: вызов field() даёт объект с сигналами value, valid, errors, touched
  • Валидация описывается декларативно в schema через правила вроде required и validate, без отдельного массива валидаторов
  • Главное отличие от реактивных форм: один источник истины-сигнал вместо параллельной синхронизации модели и FormControl

Связанные уроки

  • ng-30-reactive-forms — Signal Forms наследуют идеи реактивных форм, поэтому модель FormGroup и валидаторы нужно знать заранее
  • ng-11-signals-intro — Signal Forms построены на сигналах: signal, computed и реактивность - фундамент этого API
Signal Forms

0

1

Войти