Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Angular
Code

Введение в формы в Angular 4: шаблоны

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Introduction to Forms in Angular 4.
Introduction to Forms in Angular 4: Reactive Forms

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

Final product image
What You'll Be Creating

Формы имеют решающее значение для любого современного front-end приложения, и они являются функцией, которую мы используем каждый день, даже если этого не осознаем. Формы необходимы для безопасного входа пользователя в приложение, поиска всех доступных отелей в определенном городе, бронирования такси, составления списка дел и выполнения множества других вещей, к которым мы привыкли. В некоторых формах есть только несколько полей ввода, тогда как другие формы могут иметь массив полей, которые простираются до нескольких страниц или вкладок.

В этом уроке мы поговорим о различных стратегиях, доступных для разработки форм в Angular. Независимо от выбранной вами стратегии, вот те вещи, которые должна покрывать библиотека формы:

  • Поддержка двухсторонней привязки, чтобы значения управления входом синхронизировались с состоянием компонента.
  • Следить за состоянием формы и использовать визуальные сигналы, чтобы дать пользователю знать, валидное ли текущее состояние или нет. Например, если имя пользователя имеет недопустимые символы, то вокруг поля ввода для имени пользователя должна появиться красная рамка.
  • Иметь механизм для правильного отображения ошибок валидации.
  • Включать или отключать определенные части формы, если не соблюдены некоторые критерии валидации.

Введение в формы Angular

Angular, являющийся полнофункциональным front-end фреймворком, имеет свой собственный набор библиотек для построения сложных форм. Последняя версия Angular имеет две мощные стратегии построения форм. Вот они:

  • шаблонные формы
  • модельные или реактивные формы

Обе технологии принадлежат библиотеке @angular/forms и основаны на тех же классах управления формой. Тем не менее, они значительно отличаются в своей философии, стиле программирования и технике. Выбор одного из них зависит от вашего личного вкуса, а также от сложности формы, которую вы пытаетесь создать. На мой взгляд, сначала вы должны попробовать оба подхода, а затем выбрать тот, который соответствует вашему стилю и проекту.

В первой части учебника будут рассмотрены шаблонные формы с практическим примером: создание формы регистрации с валидацией для всех полей формы. Во второй части этого урока мы вернемся на пару шагов назад, чтобы создать ту же форму, используя подход, основанный на модели.

Шаблонные формы

Шаблонный подход - это стратегия, которая была заимствована из эпохи AngularJS. На мой взгляд, это самый простой метод построения форм. Как это работает? Мы будем использовать некоторые директивы Agnular.

Директивы позволяют прикрепить поведение к элементам в DOM.
- Документация Angular

Angular предоставляет директивы, специфичные для конкретной формы, которые вы можете использовать для привязки входных данных формы и модели. Директивы, специфичные для формы, добавляют дополнительную функциональность и поведение к простой форме HTML. Конечным результатом является то, что шаблон заботится о привязке значений к модели и проверке формы.

В этом уроке мы будем использовать шаблонные формы для создания страницы регистрации в приложении. Форма будет охватывать наиболее распространенные элементы формы и различные проверки валидации этих элементов формы. Вот шаги, которые вы проследуете в этом уроке.

  • Добавьте FormsModule в app.module.ts.
  • Создайте класс для модели User.
  • Создайте исходные компоненты и макет для формы регистрации.
  • Используйте Angular директивы формы, такие как ngModel, ngModelGroup и ngForm.
  • Добавьте валидацию с помощью встроенных валидаторов.
  • Отображать ошибки валидации.
  • Управление формой с помощью ngSubmit.

Давайте начнем.

Предпосылки

Код для этого проекта доступен в моем репозитории GitHub. Загрузите zip-архиов или клонируйте репо, чтобы увидеть его в действии. Если вы предпочитаете начинать с нуля, убедитесь, что у вас установлен Angular CLI. Используйте команду ng для создания нового проекта.

Затем создайте новый компонент для RegisterForm.

Замените содержимое app.component.html следующим образом:

Вот структура каталогов для каталога src/. Я удалил некоторые несущественные файлы, чтобы все было просто.

Как вы можете видеть, каталог для компонента RegisterForm был создан автоматически. Вот где будет находится большая часть нашего кода. Я также создал новый User.ts для хранения нашей модели User.

Шаблон HTML

Прежде чем мы погрузимся в шаблон фактического компонента, нам нужно иметь абстрактное представление о том, что мы строим. Итак, вот структура формы, которая у меня на уме. Форма регистрации будет содержать несколько полей ввода, элемент выбора и элемент флажка.

The HTML Template

Вот HTML-шаблон, который мы будем использовать для нашей страницы регистрации.

Шаблон HTML

Классы CSS, используемые в шаблоне HTML, являются частью библиотеки Bootstrap. Поскольку это не учебник по дизайну, я не буду здесь слишком много говорить о CSS-аспектах формы, если это необходимо.

Настройка базовой формы

Чтобы использовать директивы формы с шаблоном, нам нужно импортировать FormsModule из @angular/forms и добавить его в массив import в app.module.ts.

app/app.module.ts

Затем создайте класс, который будет содержать все свойства объекта User. Мы можем использовать интерфейс и реализовать его в компоненте или использовать класс TypeScript для модели.

app/User.ts

Теперь создайте экземпляр класса в компоненте RegistrationForm. Я также объявил дополнительное свойство для пола.

app/signup-form/signup-form.component.ts

Для файла signup-form.component.html я собираюсь использовать тот же шаблон HTML, который обсуждался выше, но с небольшими изменениями. Форма регистрации имеет поле выбора со списком опций. Хотя это и работает, мы сделаем это Angular способом, пройдя по списку с помощью директивы ngFor.

app/signup-form/signup-form.component.html

Затем мы хотим привязать данные формы к объекту пользовательского класса, чтобы при вводе регистрационных данных в форму был создан новый объект User, который временно сохраняет эти данные. Таким образом, вы можете синхронизировать представление с моделью, и это называется привязкой.

Есть несколько способов сделать это. Позвольте мне сначала познакомить вас с ngModel и ngForm.

ngForm и ngModel

ngForm и ngModel - это Angular директивы, которые необходимы для создания форм, управляемых шаблонами. Начнем с ngForm. Вот выдержка о ngForm из Angular docs.

Директива NgForm дополняет элемент form дополнительными функциями. Она содержит элементы управления, созданные с директивой ngModel  и атрибутом name, и отслеживает их свойства, в том числе их валидацию. Она также имеет свое собственное свойство valid, которое истинно только в том случае, если все содержащиеся в нем элементы управления валидны.

Сначала обновите форму с помощью директивы ngForm:

app/signup-form/signup-form.component.html

#signupForm - это ссылочная переменная шаблона, которая ссылается на директиву ngForm, которая управляет всей формой. В приведенном ниже примере демонстрируется использование ссылочного объекта ngForm для валидации.

app/signup-form/signup-form.component.html

Здесь signupForm.form.valid вернет false, если все элементы формы не пройдут соответствующие проверки валидации. Кнопка отправки будет отключена до тех пор, пока форма не будет валидна.

Что касается привязки шаблона и модели, существует множество способов сделать это, и ngModel имеет три разных синтаксиса для решения этой ситуации. Вот они:

  1. [(NgModel)]
  2. [NgModel]
  3. ngModel

Начнем с первого.

Двусторонняя привязка с использованием [(ngModel)]

[(ngModel)] выполняет двустороннюю привязку для чтения и записи значений управления вводом. Если используется директива [(ngModel)], поле ввода берет начальное значение из класса связанных компонентов и обновляет его, всякий раз, когда обнаруживается какое-либо изменение входного значения управления (при нажатии клавиши и нажатии кнопки). Нижеприведенное изображение описывает процесс двустороннего связывания.

Two-way binding with ngModel

Вот код для поля ввода электронной почты:

[(ngModel)] = "user.email" связывает свойство электронной почты пользователя с входным значением. Я также добавил атрибут name и установил name = "email". Это важно, и вы получите сообщение об ошибке, если вы не объявили атрибут name при использовании ngModel.

Аналогичным образом добавьте к каждому элементу формы атрибут [(ngModel)] и уникальный атрибут name. Теперь ваша форма должна выглядеть примерно так:

app/signup-form/signup-form.component.html

ngModelGroup используется для группировки одинаковых полей формы, чтобы мы могли запускать валидацию только по этим полям формы. Поскольку оба поля пароля связаны, мы помещаем их под одну группу ngModelGroup. Если все работает так, как ожидалось, свойство user, связанное с компонентом, должно отвечать за хранение всех значений управления формой. Чтобы увидеть это в действии, добавьте следующее после тега формы:

Пропустите свойство user через JsonPipe, чтобы отобразить модель как JSON в браузере. Это полезно для отладки и ведения логов. Вы должны увидеть JSON вывод следующим образом.

An example of JSON output

Значения текут от представления к модели. А как насчет другого пути? Попробуйте инициализировать объект пользователя некоторыми значениями.

app/signup-form/signup-form.component.ts

И они автоматически появляются в представлении:

Синтаксис двухсторонней привязки [(ngModel)] позволяет легко создавать формы. Однако он имеет определенные недостатки; следовательно, существует альтернативный подход, в котором используется ngModel или [ngModel].

Добавление ngModel в Mix

Когда используется ngModel, мы фактически отвечаем за обновление свойства компонента с помощью значений управления вводом и наоборот. Входные данные автоматически не поступают в пользовательское свойство компонента.

Поэтому замените все экземпляры [(ngModel)] = "" в ngModel. Мы сохраним атрибут name, потому что для всех трех версий ngModel нужен атрибут name.

app/signup-form/signup-form.component.html

С помощью ngModel значение атрибута name станет ключом signupForm ссылочного объекта ngForm, который мы создали ранее. Так, например, signupForm.value.email сохранит контрольное значение для идентификатора электронной почты.

Замените {{user | json}} на {{signupForm.value | json}}, потому что сейчас все состояние сохраняется.

Односторонняя привязка с использованием [ngModel]

Что делать, если вам нужно установить начальное состояние из компонента связанного класса? Это то, что делает для вас [ngModel].

One-way binding with ngModel

Здесь данные передаются от модели к виду. Внесите следующие изменения в синтаксис для использования односторонней привязки:

app/signup-form/signup-form.component.html

Итак, какой подход вы должны выбрать? Если вы используете [(ngModel)] и ngForm вместе, у вас в конечном итоге будет два состояния для поддержки - user и signupForm.value - что может в итоге вас запутать.

Следовательно, я рекомендую использовать метод односторонней привязки. Но решать вам.

Проверка и отображение сообщений об ошибках

Вот наши требования к валидации.

  • Все элементы управления формой обязательны.
  • Отключите кнопку отправки до тех пор, пока не будут заполнены все поля ввода.
  • В поле электронной почты должно быть строго указан идентификатор электронной почты.
  • Поле пароля должно иметь минимальную длину 8 символов. 
  • И пароль, и его подтверждение должны совпадать.
Form with Validation using Template-driven forms
Наша форма с валидацией

Сперва все просто. Вы должны добавить атрибут required проверки для каждого элемента формы следующим образом:

app/signup-form/signup-form.component.html

Помимо атрибута required, я также экспортировал новую ссылочную переменную шаблона #email. Это делается для того, чтобы вы могли получить доступ к элементу управления Angular входного окна внутри самого шаблона. Мы будем использовать его для отображения ошибок и предупреждений. Теперь используйте свойство кнопки disabled, чтобы отключить кнопку:

app/signup-form/signup-form.component.html

Чтобы добавить ограничение по электронной почте, используйте атрибут pattern, который работает с полями ввода. Шаблоны используются для указания регулярных выражений, подобных приведенным ниже:

Для поля пароля все, что вам нужно сделать, это добавить атрибут minlength = "":

app/signup-form/signup-form.component.html

Чтобы отобразить ошибки, я собираюсь использовать условную директиву ngIf для элемента div. Начнем с поля ввода для электронной почты:

app/signup-form/signup-form.component.html

Здесь много всего происходит. Начнем с первой строки раздела об ошибки.

Помните переменную #email, которую мы экспортировали ранее? Она содержит некоторую информацию о состоянии управления вводом электронной почты. Это включает в себя: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched и email.errors. На приведенном ниже изображении подробно описывается каждое из этих свойств.

Different class properties for displaying errors

Таким образом, элемент div с *ngIf будет отображаться только в том случае, если email невалидный. Тем не менее, пользователь будет встречен с ошибками о том, что поля ввода пустые, даже если у них есть возможность редактировать форму.

Чтобы избежать подобного сценария, мы добавили второе условие. Ошибка будет отображаться только после посещения элемента управления или изменения значения элемента управления.

Вложенные элементы div используются для покрытия всех случаев ошибок проверки. Мы используем email.errors для проверки всех возможных ошибок валидации и последующего отображения их пользователю в виде собственных сообщений. Теперь следуйте той же процедуре для других элементов формы. Вот как я закодировал проверку паролей.

app/signup-form/signup-form.component.html

Все это начинает выглядеть немного грязно. Angular имеет ограниченный набор атрибутов валидатора: required, minlength, maxlength и template. Чтобы охватить любой другой сценарий, подобный сценарию сравнения паролей, вам придется полагаться на вложенные условия ngIf, как я уже говорил выше. Или, в идеале, создать пользовательскую функцию валидатора, о которой я расскажу в третьей части этой серии.

В приведенном выше коде я использовал синтаксис ngIf else, который был введен в последней версии Angular. Вот как это работает:

Отправить форму с помощью ngSubmit

Мы почти закончили форму. Теперь мы должны иметь возможность отправить форму, и контроль данных формы должен быть передан компонентному методу, например onFormSubmit().

app/signup-form/signup-form.component.ts

Теперь для компонента:

app/signup-form/signup-form.component.ts

Финальная демонстрация

Вот окончательная версия приложения. Я добавил несколько классов bootstrap, чтобы сделать форму красивой.

Резюме

На этом мы заканчиваем. В этом уроке мы рассмотрели все, что вам нужно знать о создании формы в Angular, используя подход, основанный на шаблонах. Шаблонные формы популярны благодаря своей простоте и легком использовании.

Однако, если вам нужно создать форму с большим количеством элементов, этот подход станет весьма грязным. Итак, в следующем уроке мы рассмотрим модельный способ построения одной и той же формы.

Поделитесь своими мыслями в комментариях ниже.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.