Angular

Template-driven формы

Форма обратной связи с тремя полями. Реактивная форма потребует объявить FormGroup в классе, связать каждый контрол и продублировать имена в шаблоне. Template-driven подход обходится одной директивой ngModel на каждом поле: модель строится автоматически из самой разметки. Для коротких форм это самый прямой путь, и в Angular 21 он по-прежнему поддерживается наравне с остальными.

  • Формы логина и подписки на рассылку: два-три поля, минимум логики
  • Настройки профиля: набор переключателей и текстовых полей, привязанных напрямую к объекту модели
  • Поиск и фильтры: одно поле с ngModel и debounce через valueChanges формы
  • Прототипы и админки: быстрый CRUD-экран, где скорость важнее тонкого контроля
  • Анкеты с условными полями: ngIf плюс ngModel показывает дополнительные поля по ответу

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

  • Property binding [value] и event binding (input) в шаблоне Angular
  • Понимание двусторонней привязки и синтаксиса banana-in-a-box [()]
  • Базовое знание standalone-компонентов и импорта в imports

Две модели форм с самого начала

Angular 2 (2016) принёс сразу два модуля форм: FormsModule для template-driven подхода и ReactiveFormsModule для реактивного. Template-driven формы унаследовали идею из AngularJS, где ng-model двусторонне связывал поле ввода с моделью прямо в разметке. Реактивный подход добавили для крупных форм со сложной логикой. В Angular 21 (2025) оба остаются актуальными, а к ним добавился третий вариант - Signal Forms. Template-driven форма не устарела: для простых случаев это меньше кода.

ngModel и двусторонняя привязка

Директива ngModel связывает элемент ввода со свойством компонента. В двустороннем варианте [(ngModel)] значение течёт в обе стороны: ввод пользователя обновляет свойство, а изменение свойства в коде обновляет поле. Для работы ngModel компонент импортирует FormsModule.

Каждый контрол с ngModel внутри тега form обязан иметь атрибут name. По этому имени Angular регистрирует контрол в модели формы. Без name директива выбросит ошибку, потому что не сможет понять, под каким ключом хранить значение.

Синтаксис [(ngModel)] - это сахар над парой [ngModel]="value" и (ngModelChange)="value = $event". Понимание этого помогает, когда нужна асимметрия: например, читать значение, но перехватывать изменение для трансформации.

Что именно делает синтаксис [(ngModel)]="email"?

ngForm: агрегирование контролов

Директива ngForm автоматически применяется к каждому тегу form в шаблоне, где импортирован FormsModule. Она собирает все вложенные ngModel в единый объект NgForm с агрегированными значениями (form.value), общим статусом валидности (form.valid) и состояниями touched и dirty.

Переменная #form="ngForm" даёт доступ к экземпляру NgForm прямо в шаблоне. Кнопка блокируется, пока form.invalid, а событие ngSubmit передаёт собранный объект form.value в метод компонента. Имена контролов становятся ключами этого объекта.

Группировать поля внутри формы помогает директива ngModelGroup: она создаёт вложенный объект в form.value. Например, ngModelGroup="address" соберёт street и city в address: { street, city }.

Откуда берутся ключи объекта form.value в template-driven форме?

Валидация в шаблоне и когда выбрать этот подход

Валидация в template-driven формах задаётся атрибутами прямо в разметке. Стандартные HTML-атрибуты required, minlength, maxlength, pattern Angular превращает в валидаторы. Состояние каждого контрола доступно через его собственную template reference variable, привязанную к ngModel.

Переменная #emailCtrl="ngModel" даёт доступ к состоянию контрола: invalid, touched, errors. Ошибки показываются только после touched, чтобы не пугать пользователя красным до первого взаимодействия. Объект errors содержит ключи сработавших валидаторов.

  • Когда template-driven подходит — Простые формы с фиксированным набором полей, минимум динамики, быстрый прототип. Логика валидации укладывается в стандартные атрибуты
  • Когда лучше reactive или signal forms — Динамическое добавление полей, сложная кросс-валидация, реакция на valueChanges, юнит-тесты модели формы без рендера разметки

Модель template-driven формы живёт в шаблоне, а не в коде. Это усложняет юнит-тестирование и программное управление формой. Как только появляется сложная зависимость между полями, стоит переходить на reactive или signal forms.

Для какой задачи template-driven форма - разумный выбор по сравнению с reactive?

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

Template-driven формы - первый из трёх подходов к формам в курсе:

  • Привязки шаблона — ngModel построен поверх property и event binding, основа двусторонней связи
  • Reactive forms — Следующий шаг: модель формы переносится в код для сложной логики и динамики

Итог

  • Template-driven форма строит модель из самой разметки через директиву ngModel, требуется FormsModule
  • Двусторонняя привязка [(ngModel)] синхронизирует поле ввода и свойство компонента в обе стороны
  • Директива ngForm на теге form собирает все ngModel в единый объект формы со статусом и значениями
  • Валидация задаётся атрибутами HTML (required, minlength) плюс директивами Angular, состояние видно через template reference variable
  • Подход выигрывает на простых формах, но плохо масштабируется на сложную динамику и тестирование

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

  • ng-04-templates-binding — Template-driven формы построены на привязках шаблона, поэтому property и event binding нужно знать заранее
  • ng-30-reactive-forms — Поняв ограничения шаблонного подхода, разработчик переходит к реактивным формам с моделью в коде
Template-driven формы

0

1

Войти