Angular Reactive Forms представляют собой основанную на модели альтернативу традиционным формам на основе шаблонов. Они более надежны и масштабируемы, чем формы на основе шаблонов. Подробнее о реактивных формах и их отличиях от форм на основе шаблонов см. в статье Реактивные и управляемые шаблонами формы в Angular документации Angular.

Элементы управления вводом Wijmo могут использоваться в обоих типах форм и приносят обычные преимущества в обоих случаях:

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

Шаг 1: Простая реактивная форма

Начнем с простого примера реактивной формы, взятого прямо из Документации Angular.

Это наша версия образца.

Файл app.module.ts импортирует ReactiveFormsModule из Angular, который предоставляет всю инфраструктуру, используемую формой.

Файл my-form.component.ts определяет модель, управляющую формой. Обратите внимание на иерархическую структуру модели и на то, как в ней указаны некоторые валидаторы:

export class MyFormComponent {
  profileForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.fb.group({
      street: [''],
      city: [''],
      state: [''],
      zip: ['']
    }),
    aliases: this.fb.array([
      this.fb.control('')
    ])
  });

И my-form.component.html содержит разметку, определяющую форму:

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
  <label>
    First Name:
    <input type="text" formControlName="firstName" required>
  </label>
  <label>
    Last Name:
    <input type="text" formControlName="lastName">
  </label>
  <div formGroupName="address">
    <h3>Address</h3>
    <label>
      Street:
      <input type="text" formControlName="street">
    </label>

Обратите внимание, как в разметке используется атрибут formControlName для указания привязок вместо традиционной директивы ngModel, и как используются вложенные элементы div с formGroupNameатрибут, поэтому форма и модель имеют одинаковую иерархию.

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

Шаг 2: Замена HTML-элементов элементами управления Wijmo

На этом этапе мы заменим основные элементы ввода в нашей форме более мощными элементами управления Wijmo.

Это переработанная версия образца

Чтобы использовать Wijmo, мы начинаем с добавления ссылки на пакет Wijmo NPM. Поскольку мы используем Stackblitz, это делается путем ввода «Wijmo» на панели зависимостей нашего проекта:

В автономных проектах мы бы сделали это, набрав «npm install wijmo» в командной строке.

Теперь, когда пакет Wijmo установлен, мы импортируем его в приложение, изменив файл app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { MyFormComponent } from './my-form/my-form.component';
import { WjInputModule } from 'wijmo/wijmo.angular2.input';
@NgModule({
  declarations: [
    AppComponent,
    MyFormComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    WjInputModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Прежде чем использовать какие-либо элементы управления Wijmo, нам нужно импортировать CSS Wijmo. Чтобы добавить материальную тему Wijmo в наше приложение, мы добавляем в файл styles.css следующее:

/* Wijmo Styles */
@import "wijmo/styles/themes/wijmo.theme.material.css";
.wj-control {
  background-color: #e7f5f5
}

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

Вот как выглядит файл my-form.component.html:

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
  <label>
    First Name:
    <wj-combo-box formControlName="firstName" required></wj-combo-box>
  </label>
  <label>
    Last Name:
    <wj-combo-box formControlName="lastName"></wj-combo-box>
  </label>
  <label>
    Birthday:
    <wj-input-date formControlName="birthday"
      [isRequired]="false"
      [format]="'MMMM d'"></wj-input-date>
  </label>
  <label>
    Team Size:
    <wj-input-number formControlName="teamsize" required 
      [min]="1" 
      [max]="10" 
      [step]="1"></wj-input-number>
  </label>

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

Обратите также внимание на разметку:

  1. Использует свойство isRequired элементов управления вводом Wijmo вместо атрибута required, применимого только к элементам ввода,
  2. Задает формат для элемента управления InputDate для отображения даты в нужном нам формате (в данном случае только день и месяц),
  3. Задает значения min и max для элемента управления InputNumber, чтобы пользователь не мог вводить значения за пределами допустимого диапазона. (нет необходимости в валидаторе).

Теперь форма выглядит и работает лучше. Элементы управления InputDate, InputNumber и ComboBox упрощают ввод данных и снижают вероятность ошибок:

Шаг 3: Усовершенствованная проверка и стилизация

На этом этапе мы добавим некоторые стили, чтобы существенно улучшить удобство использования формы.

Это окончательный вариант образца.

Начнем с добавления в проект нового файла CSS: wijmo.labeled-input.css и ссылки на него из файла styles.css:

Файл wijmo.labeled-input.css содержит правила CSS, которые используют преимущества встроенных псевдоселекторов Wijmo для реализации таких функций, как анимированные плавающие метки и элементы фокуса для элементов управления вводом Wijmo.

Чтобы включить новый стиль, мы должны изменить разметку в my-form.component.html и обернуть каждый элемент ввода в div с классом wj-labeled-input:

<form [formGroup]="profileForm" ngNativeValidate (ngSubmit)="onSubmit()">
  <h3>Personal Info</h3>
  <div class="wj-labeled-input">
    <wj-combo-box formControlName="firstName"></wj-combo-box>
    <label>First Name</label>
    <div class="wj-error" tabindex="-1">Please tell us your first name</div>
  </div>
  <div class="wj-labeled-input">
    <wj-combo-box formControlName="lastName"></wj-combo-box>
    <label>Last Name</label>
    <div class="wj-error" tabindex="-1">Please tell us your last name</div>
  </div>
  <div class="wj-labeled-input">
    <wj-input-date formControlName="birthday"
      [isRequired]="false"
      [format]="'MMMM d'"></wj-input-date>
    <label>Birthday</label>
  </div>
  <div class="wj-labeled-input narrow">
    <wj-input-number formControlName="teamsize"
      [isRequired]="false"
      [min]="1" 
      [max]="10" 
      [step]="1"></wj-input-number>
    <label>Team Size</label>
  </div>

Элементы wj-labeled-input содержат:

  1. Элемент управления вводом Wijmo, используемый для редактирования значения,
  2. Элемент метки, который используется в качестве заполнителя, когда элемент управления пуст, и в качестве заголовка, когда он имеет содержимое.
  3. Необязательный элемент ошибки, который отображается, когда элемент управления был затронут и находится в недопустимом состоянии.

Улучшенные стили

Новый CSS и скорректированная разметка делают форму отзывчивой (более эффективно используется пространство, доступное на больших и маленьких экранах).

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

Доступность улучшена благодаря анимированному элементу подчеркивания, указывающему на сфокусированные элементы управления:

Улучшенная проверка

Первоначальная версия приложения использовала эту разметку, чтобы отключить кнопку «Отправить», пока форма не станет действительной:

<button type="submit" [disabled]="!profileForm.valid">
    Submit
</button>

Этот подход работает, но меня расстраивает то, что кнопка «Отправить» отключена, и нет никаких указаний, показывающих, что форма в настоящее время недействительна.

Чтобы исправить эту ситуацию, в последней версии приложения мы убрали атрибут disabled с кнопки Submit и добавили в форму директиву ngNativeValidate:

<form [formGroup]="profileForm" ngNativeValidate (ngSubmit)="onSubmit()">

Это позволяет пользователям щелкнуть форму отправки и получить сообщения об ошибках, показывающие, какие поля недействительны:

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

Вывод

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

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

Удачного кодирования! Если у вас есть вопросы или комментарии, обязательно напишите их ниже.

от Бернардо де Кастильо

Первоначально опубликовано на GrapeCity.com