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 — Поняв ограничения шаблонного подхода, разработчик переходит к реактивным формам с моделью в коде