Создание формы на основе шаблона
В этом руководстве показано, как создать форму на основе шаблона. Элементы управления в форме связаны со свойствами данных, для которых выполняется проверка ввода. Проверка ввода помогает поддерживать целостность данных, а стилизация — улучшать взаимодействие с пользователем.
Формы на основе шаблонов используют двустороннюю привязку данных, чтобы обновлять модель данных в компоненте при внесении изменений в шаблон, и наоборот.
Формы на основе шаблонов и реактивные формы
Angular поддерживает два подхода к проектированию интерактивных форм. Формы на основе шаблонов позволяют использовать в шаблоне Angular специальные директивы для форм. Реактивные формы предлагают управляемый моделью подход к созданию форм.
Формы на основе шаблонов отлично подходят для небольших или простых форм, а реактивные формы лучше масштабируются и подходят для сложных форм. Сравнение этих подходов см. в разделе Выбор подхода
С помощью шаблона Angular можно создавать практически любые формы — формы входа, контактные формы и почти любые деловые формы. Вы можете творчески располагать элементы управления и связывать их с данными объектной модели. Можно задавать правила проверки и отображать ошибки проверки, условно разрешать ввод в определенных элементах управления, запускать встроенную визуальную обратную связь и многое другое.
Цели
В этом руководстве вы узнаете, как выполнить следующие задачи:
- Создать форму Angular с компонентом и шаблоном
- Использовать
ngModelдля создания двусторонних привязок данных, позволяющих читать и записывать значения элементов управления вводом - Обеспечить визуальную обратную связь с помощью специальных классов CSS, отслеживающих состояние элементов управления
- Отображать пользователям ошибки проверки и условно разрешать ввод в элементах управления формы в зависимости от состояния формы
- Обмениваться информацией между элементами HTML с помощью переменных-ссылок шаблона
Создание формы на основе шаблона
Формы на основе шаблонов используют директивы, определенные в FormsModule.
| Директивы | Описание |
|---|---|
NgModel | Согласует изменения значения связанного элемента формы с изменениями модели данных, позволяя реагировать на ввод пользователя с помощью проверки ввода и обработки ошибок. |
NgForm | Создает экземпляр верхнего уровня FormGroup и связывает его с элементом <form> для отслеживания совокупного значения и состояния проверки формы. Как только вы импортируете FormsModule, эта директива по умолчанию становится активной для всех тегов <form>. Добавлять специальный селектор не нужно. |
NgModelGroup | Создает экземпляр FormGroup и связывает его с элементом DOM. |
Обзор шагов
В ходе этого руководства вы свяжете пример формы с данными и обработаете ввод пользователя, выполнив следующие действия.
- Создайте базовую форму.
- Определите пример модели данных
- Добавьте необходимые инфраструктурные элементы, например
FormsModule
- Свяжите элементы управления формы со свойствами данных с помощью директивы
ngModelи синтаксиса двусторонней привязки данных. - Отслеживайте допустимость ввода и состояние элементов управления с помощью
ngModel.- Добавьте собственный CSS для визуальной обратной связи о состоянии
- Показывайте и скрывайте сообщения об ошибках проверки
- Реагируйте на событие нажатия встроенной кнопки HTML, добавляя данные в модель.
- Обрабатывайте отправку формы с помощью выходного свойства
ngSubmitформы.- Отключите кнопку Отправить, пока форма не станет допустимой
- После отправки замените заполненную форму другим содержимым на странице
Создание формы
-
В предоставленном примере приложения создается класс
Actor, определяющий модель данных, отраженную в форме.export class Actor { constructor( public id: number, public name: string, public skill: string, public studio?: string, ) {} } -
Макет и подробности формы определяются в классе
ActorFormComponent.import {Component} from '@angular/core'; import {Actor} from '../actor'; import {FormsModule} from '@angular/forms'; import {JsonPipe} from '@angular/common'; @Component({ selector: 'app-actor-form', templateUrl: './actor-form.component.html', imports: [FormsModule, JsonPipe], }) export class ActorFormComponent { skills = ['Method Acting', 'Singing', 'Dancing', 'Swordfighting']; model = new Actor(18, 'Tom Cruise', this.skills[3], 'CW Productions'); submitted = false; onSubmit() { this.submitted = true; } }Значение
selectorкомпонента "app-actor-form" означает, что эту форму можно добавить в родительский шаблон с помощью тега<app-actor-form>. -
Следующий код создает новый экземпляр актера, чтобы при первоначальном отображении формы можно было показать пример актера.
const myActress = new Actor(42, 'Marilyn Monroe', 'Singing'); console.log('My actress is called ' + myActress.name); // "My actress is called Marilyn"В этой демонстрации используются фиктивные данные для
modelиskills. В реальном приложении вы внедрили бы службу данных для получения и сохранения настоящих данных либо предоставили бы эти свойства в качестве входных и выходных данных. -
Компонент включает функциональность форм, импортируя модуль
FormsModule.@Component({ selector: 'app-actor-form', templateUrl: './actor-form.component.html', imports: [FormsModule, JsonPipe], }) export class ActorFormComponent { -
Форма отображается в макете приложения, определенном в шаблоне корневого компонента.
<app-actor-form />
Исходный шаблон задает макет формы с двумя группами элементов формы и кнопкой отправки. Группы соответствуют двум свойствам модели данных Actor: name и studio. У каждой группы есть метка и поле для ввода пользователем данных.
- Элемент управления
<input>Имя имеет атрибут HTML5required - Элемент управления
<input>Студия не имеет его, посколькуstudioявляется необязательным
К кнопке Отправить применено несколько классов для стилизации. На этом этапе макет формы представляет собой обычный HTML5 без привязок и директив.
- Элемент управления
-
В примере формы используются некоторые классы стилей из Twitter Bootstrap:
container,form-group,form-controlиbtn. Чтобы использовать эти стили, таблица стилей приложения импортирует библиотеку.@import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css'); -
Для формы требуется, чтобы навык актера выбирался из предварительно заданного списка
skills, который хранится внутриActorFormComponent. Цикл Angular@forперебирает значения данных, чтобы заполнить элемент<select>.<div class="form-group"> <label for="skill">Skill</label> <select class="form-control" id="skill" required> @for (skill of skills; track $index) { <option [value]="skill">{{ skill }}</option> } </select> </div>
Если запустить приложение сейчас, в элементе выбора отобразится список навыков. Элементы ввода пока не связаны со значениями данных или событиями, поэтому они остаются пустыми и не выполняют никаких действий.
Привязка элементов управления вводом к свойствам данных
Следующий шаг — связать элементы управления вводом с соответствующими свойствами Actor с помощью двусторонней привязки данных, чтобы они реагировали на ввод пользователя, обновляя модель данных, а также реагировали на программные изменения данных, обновляя отображение.
Директива ngModel, объявленная в FormsModule, позволяет связывать элементы управления в форме на основе шаблона со свойствами модели данных. Если добавить директиву с помощью синтаксиса двусторонней привязки данных, [(ngModel)], Angular сможет отслеживать значение элемента управления и взаимодействие с ним пользователя, а также синхронизировать представление с моделью.
- Отредактируйте файл шаблона
actor-form.component.html. - Найдите тег
<input>рядом с меткой Имя. - Добавьте директиву
ngModel, используя синтаксис двусторонней привязки данных[(ngModel)]="...".
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" />
TODO: remove this: {{ model.name }}
ПОЛЕЗНО: В этом примере после каждого тега ввода временно добавлено диагностическое выражение интерполяции {{model.name}}, чтобы показывать текущее значение соответствующего свойства данных. Комментарий напоминает, что после проверки работы двусторонней привязки данных эти диагностические строки нужно удалить.
Доступ к общему состоянию формы
После импорта FormsModule в компонент Angular автоматически создал директиву NgForm и прикрепил ее к тегу <form> в шаблоне (поскольку у NgForm есть селектор form, который соответствует элементам <form>).
Чтобы получить доступ к NgForm и общему состоянию формы, объявите переменную-ссылку шаблона.
-
Отредактируйте файл шаблона
actor-form.component.html. -
Обновите тег
<form>, добавив переменную-ссылку шаблона#actorForm, и задайте ее значение следующим образом.<form #actorForm="ngForm">
Теперь переменная шаблона
actorFormссылается на экземпляр директивыNgForm, управляющей формой в целом. -
Запустите приложение.
-
Начните вводить текст в поле Имя.
При добавлении и удалении символов вы увидите, как они появляются и исчезают в модели данных.
Диагностическая строка с интерполированными значениями показывает, что значения действительно передаются из поля ввода в модель и обратно.
Именование элементов управления
При использовании [(ngModel)] для элемента необходимо определить для него атрибут name. Angular использует заданное имя, чтобы зарегистрировать элемент в директиве NgForm, связанной с родительским элементом <form>.
В примере элементу <input> добавлен атрибут name со значением "name", что логично для имени актера. Подойдет любое уникальное значение, но полезно использовать описательное имя.
- Добавьте аналогичные привязки
[(ngModel)]и атрибутыnameдля элементов Студия и Навык. - Теперь можно удалить диагностические сообщения с интерполированными значениями.
- Чтобы убедиться, что двусторонняя привязка данных работает для всей модели актера, добавьте в начало шаблона компонента новую текстовую привязку с каналом
json, который сериализует данные в строку.
После этих изменений шаблон формы должен выглядеть следующим образом:
{{ model | json }}
<div class="form-group">
<label for="name">Name</label>
<input
type="text"
class="form-control"
id="name"
required
[(ngModel)]="model.name"
name="name"
/>
</div>
<div class="form-group">
<label for="studio">Studio</label>
<input
type="text"
class="form-control"
id="studio"
[(ngModel)]="model.studio"
name="studio"
/>
</div>
<div class="form-group">
<label for="skill">Skill</label>
<select class="form-control" id="skill" required [(ngModel)]="model.skill" name="skill">
@for (skill of skills; track $index) {
<option [value]="skill">{{ skill }}</option>
}
</select>
</div>
Обратите внимание на следующее:
-
У каждого элемента
<input>есть свойствоid. Оно используется атрибутомforэлемента<label>, чтобы связать метку с элементом управления вводом. Это стандартная функция HTML. -
У каждого элемента
<input>также есть обязательное свойствоname, которое Angular использует для регистрации элемента управления в форме.
После проверки результатов можно удалить текстовую привязку {{ model | json }}.
Отслеживание состояний формы
После отправки формы Angular применяет класс ng-submitted к элементам form. Этот класс можно использовать, чтобы изменить стиль формы после ее отправки.
Отслеживание состояний элементов управления
Добавление директивы NgModel к элементу управления добавляет к нему имена классов, описывающих его состояние. Эти классы можно использовать, чтобы изменить стиль элемента управления в зависимости от его состояния.
В следующей таблице описаны имена классов, которые Angular применяет в зависимости от состояния элемента управления.
| Состояние | Класс, если истинно | Класс, если ложно |
|---|---|---|
| Элемент управления посещен. | ng-touched | ng-untouched |
| Значение элемента управления изменено. | ng-dirty | ng-pristine |
| Значение элемента управления допустимо. | ng-valid | ng-invalid |
При отправке Angular также применяет класс ng-submitted к элементам form, но не к элементам управления внутри элемента form.
Используйте эти классы CSS, чтобы задать стили элементов управления в зависимости от их состояния.
Наблюдение за состояниями элементов управления
Чтобы посмотреть, как платформа добавляет и удаляет классы, откройте инструменты разработчика браузера и изучите элемент <input>, соответствующий имени актера.
-
С помощью инструментов разработчика браузера найдите элемент
<input>, соответствующий полю ввода Имя. Вы увидите, что у элемента есть несколько классов CSS помимо "form-control". -
При первом отображении классы указывают, что значение допустимо, не менялось после инициализации или сброса и что элемент управления не посещался после инициализации или сброса.
<input class="form-control ng-untouched ng-pristine ng-valid" />;
-
Выполните следующие действия с полем
<input>Имя и проследите, какие классы появляются.-
Посмотрите, но не касайтесь. Классы указывают, что элемент не затронут, не изменен и имеет допустимое значение.
-
Щелкните поле имени, затем щелкните за его пределами. Элемент управления теперь посещен, и у элемента появился класс
ng-touchedвместо классаng-untouched. -
Добавьте косые черты в конец имени. Теперь элемент затронут и изменен.
-
Удалите имя. Значение станет недопустимым, поэтому класс
ng-invalidзаменит классng-valid.
-
Создание визуальной обратной связи для состояний
Пара ng-valid/ng-invalid особенно интересна, поскольку при недопустимых значениях важно подать заметный визуальный сигнал. Также нужно помечать обязательные поля.
Обязательные поля и недопустимые данные можно одновременно обозначить цветной полосой слева от поля ввода.
Чтобы изменить внешний вид таким образом, выполните следующие действия.
-
Добавьте определения для классов CSS
ng-*. -
Добавьте эти определения классов в новый файл
forms.css. -
Добавьте новый файл в проект рядом с
index.html:.ng-valid[required], .ng-valid.required { border-left: 5px solid #42A948; /* green */ } .ng-invalid:not(form) { border-left: 5px solid #a94442; /* red */ } -
В файле
index.htmlобновите тег<head>, включив в него новую таблицу стилей.<link rel="stylesheet" href="assets/forms.css" />
Показ и скрытие сообщений об ошибках проверки
Поле ввода Имя является обязательным, и при его очистке полоса становится красной. Это указывает на проблему, но пользователь не знает, в чем она заключается и что делать. Можно показать полезное сообщение, проверяя состояние элемента управления и реагируя на него.
Поле выбора Навык также является обязательным, но для него не нужна такая обработка ошибок, поскольку поле выбора уже ограничивает варианты допустимыми значениями.
Чтобы определить и при необходимости показывать сообщение об ошибке, выполните следующие действия.
-
Добавление локальной ссылки на элемент ввода
Дополните тег
inputпеременной-ссылкой шаблона, с помощью которой можно получить доступ к элементу управления Angular поля ввода из шаблона. В примере эта переменная называется#name="ngModel".Переменной-ссылке шаблона (
#name) присваивается значение"ngModel", поскольку это значение свойстваNgModel.exportAs. Это свойство указывает Angular, как связать переменную-ссылку с директивой. -
Добавление сообщения об ошибке
Добавьте элемент
<div>с подходящим сообщением об ошибке. -
Условное отображение сообщения об ошибке
Показывайте или скрывайте сообщение, связав свойства элемента управления
nameсо свойствомhiddenэлемента<div>сообщения. -
Добавление условного сообщения об ошибке для имени
Добавьте условное сообщение об ошибке для поля ввода
name, как в следующем примере.<label for="name">Name</label> <input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #name="ngModel" /> <div [hidden]="name.valid || name.pristine" class="alert alert-danger"> Name is required </div>
<div [hidden]="name.valid || name.pristine" class="alert alert-danger">
В этом примере сообщение скрывается, если элемент управления допустим или находится в состоянии pristine (не изменен). Это означает, что пользователь не менял значение с момента отображения формы. Если не учитывать состояние pristine, сообщение будет скрываться только при допустимом значении. Если открыть этот компонент с новым пустым актером или актером с недопустимыми данными, сообщение об ошибке появится сразу, еще до выполнения каких-либо действий.
Возможно, вы захотите показывать сообщение только после того, как пользователь внесет недопустимое изменение. Скрытие сообщения, пока элемент управления находится в состоянии pristine, позволяет достичь этой цели. Значение этого решения станет понятно на следующем шаге, когда вы добавите в форму нового актера.
Добавление нового актера
В этом упражнении показано, как реагировать на событие нажатия встроенной кнопки HTML, добавляя данные в модель. Чтобы пользователи формы могли добавлять новых актеров, вы добавите кнопку Новый актер, реагирующую на щелчок.
-
В нижней части формы добавьте в шаблон элемент
<button>с надписью "Новый актер". -
В файле компонента добавьте метод создания актера в модель данных актера.
newActor() { this.model = new Actor(42, '', ''); } -
Свяжите событие щелчка кнопки с методом создания актера
newActor().<button type="button" class="btn btn-default" (click)="newActor()">New Actor</button>
-
Снова запустите приложение и нажмите кнопку Новый актер.
Форма очищается, а полосы обязательных полей слева от полей ввода становятся красными, указывая на недопустимые свойства
nameиskill. Обратите внимание, что сообщения об ошибках скрыты. Это происходит потому, что форма не изменена: вы еще ничего не меняли. -
Введите имя и снова нажмите Новый актер.
Теперь приложение отображает сообщение об ошибке
Name is required, поскольку поле ввода больше не находится в исходном состоянии. Форма помнит, что вы ввели имя до нажатия кнопки Новый актер. -
Чтобы восстановить исходное состояние элементов управления формы, сбросьте все флаги программно, вызвав метод
reset()формы после вызова методаnewActor().<button type="button" class="btn btn-default" (click)="newActor(); actorForm.reset()"> New Actor </button>Теперь при нажатии кнопки Новый актер сбрасывается и форма, и флаги ее элементов управления.
Отправка формы с помощью ngSubmit
Пользователь должен иметь возможность отправить форму после заполнения. Кнопка Отправить в нижней части формы сама по себе ничего не делает, но из-за своего типа (type="submit") она вызывает событие отправки формы.
Чтобы отреагировать на это событие, выполните следующие действия.
-
Обработка ngOnSubmit
Свяжите событие
ngSubmitформы с методомonSubmit()компонента actor-form.<form (ngSubmit)="onSubmit()" #actorForm="ngForm">
-
Привязка свойства disabled
Используйте переменную-ссылку шаблона
#actorForm, чтобы получить доступ к форме, содержащей кнопку Отправить, и создать привязку события.Свяжите свойство формы, указывающее ее общую допустимость, со свойством
disabledкнопки Отправить.<button type="submit" class="btn btn-success" [disabled]="!actorForm.form.valid"> Submit </button> -
Запуск приложения
Обратите внимание, что кнопка активна, хотя пока она не выполняет полезных действий.
-
Удаление значения поля «Имя»
Это нарушает правило "обязательное", поэтому отображается сообщение об ошибке — и, обратите внимание, кнопка Отправить также отключается.
Не нужно явно связывать активность кнопки с допустимостью формы.
FormsModuleделает это автоматически, когда вы определяете переменную-ссылку шаблона для расширенного элемента формы, а затем ссылаетесь на эту переменную в элементе управления кнопкой.
Реакция на отправку формы
Чтобы отобразить ответ на отправку формы, можно скрыть область ввода данных и показать вместо нее другое содержимое.
-
Обертывание формы
Оберните всю форму в
<div>и свяжите его свойствоhiddenсо свойствомActorFormComponent.submitted.<div [hidden]="submitted"> <h1>Actor Form</h1> <form (ngSubmit)="onSubmit()" #actorForm="ngForm"> <!-- ... all of the form ... --> </form> </div>Основная форма видна изначально, потому что свойство
submittedимеет значение false до отправки формы, как показано в этом фрагменте изActorFormComponent:submitted = false; onSubmit() { this.submitted = true; }При нажатии кнопки Отправить флаг
submittedстановится равным true, и форма исчезает. -
Добавление состояния отправки
Чтобы показать другое содержимое, пока форма находится в состоянии отправки, добавьте следующий HTML под новой оберткой
<div>.<div [hidden]="!submitted"> <h2>You submitted the following:</h2> <div class="row"> <div class="col-xs-3">Name</div> <div class="col-xs-9">{{ model.name }}</div> </div> <div class="row"> <div class="col-xs-3">Studio</div> <div class="col-xs-9">{{ model.studio }}</div> </div> <div class="row"> <div class="col-xs-3">Skill</div> <div class="col-xs-9">{{ model.skill }}</div> </div> <br /> <button type="button" class="btn btn-primary" (click)="submitted = false">Edit</button> </div>Этот
<div>, отображающий актера только для чтения с привязками интерполяции, появляется только тогда, когда компонент находится в состоянии отправки.В альтернативном представлении есть кнопка Изменить, событие щелчка которой связано с выражением, сбрасывающим флаг
submitted. -
Проверка кнопки «Изменить»
Нажмите кнопку Изменить, чтобы вернуться к редактируемой форме.
Итоги
Форма Angular, рассмотренная на этой странице, использует следующие возможности платформы для поддержки изменения данных, проверки и других функций.
- Шаблон HTML-формы Angular
- Класс компонента формы с декоратором
@Component - Обработка отправки формы путем привязки к свойству события
NgForm.ngSubmit - Переменные-ссылки шаблона, такие как
#actorFormи#name -
Синтаксис
[(ngModel)]для двусторонней привязки данных - Использование атрибутов
nameдля проверки и отслеживания изменений элементов формы - Свойство
validпеременной-ссылки для элементов ввода указывает, допустимо ли значение элемента управления или следует ли показывать сообщения об ошибках - Управление активностью кнопки Отправить путем привязки к свойству допустимости
NgForm - Пользовательские классы CSS, обеспечивающие визуальную обратную связь для недопустимых элементов управления
Ниже приведен код окончательной версии приложения:
Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/forms/template-driven-forms