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

В Angular есть два подхода работы с формами: шаблонный (template-driven) и реактивный, или модельный (reactive, model-driven). Шаблонный подход – это стандартный способ работы с формами в Angular. В шаблонных формах используются специальные директивы для сборки внутреннего представления формы. А реактивные формы позволяют вам создать собственное представление формы в классе компонента.

Примечание: Реактивные формы появились в Angular 2.

У реактивных форм есть ряд преимуществ:

  • Поддержка пользовательских валидаторов
  • Динамическое изменение валидаторов
  • Динамическое добавление полей формы

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

Требования

Для выполнения этого мануала вам понадобится:

  • Локальная установка Node.js (здесь вы найдете инструкции для macOSDebianUbuntuCentos).
  • Базовые навыки работы с Angular. Также предполагается, что вы работаете со свежим проектом Angular, созданным при помощи @angular/cli.

Это руководство было протестировано на Node v15.1.0, npm v6.14.8, @angular/core v11.0.0 и @angular/forms v11.0.0.

1: Настройка проекта

Прежде всего давайте соберем стандартный проект Angular, сгенерированный с помощью @angular/cli.

npx @angular/cli new angular-reactive-forms-example --style=css --routing=false --skip-tests

Эта команда настроит новый базовый проект Angular со стилями CSS (также доступны Sass, Less и Stylus), без маршрутизации и тестов.

Перейдите в каталог нового проекта:

cd angular-reactive-forms-example

Для работы с реактивными формами нужно использовать ReactiveFormsModule, а не FormsModule. Давайте откроем файл app.module.ts в редакторе кода и добавим ReactiveFormsModule:

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

Теперь у вас есть новый проект Angular с поддержкой реактивных форм.

2: Добавление формы в шаблон компонента

Вся логика реактивных форм полностью объявляется в классе компонента.

Откройте файл src/app/app.component.html в редакторе кода и добавьте следующие строки:

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
<div>
<label>
Name:
<input formControlName="name" placeholder="Your name">
</label>
</div>
<div>
<label>
Email:
<input formControlName="email" placeholder="Your email">
</label>
</div>
<div>
<label>
Message:
<input formControlName="message" placeholder="Your message">
</label>
</div>
<button type="submit">Send</button>
</form>

Этот код создаст форму с тремя полями: name, email и message (имя, адрес электронной почты и сообщение соответственно). Также в форме будет кнопка с надписью «Send». При отправке формы будет вызван метод onSubmit(myForm).

Примечание: В Angular 2.x следует также добавить директиву novalidate с открывающим тегом form, поскольку эти версии Angular переопределяют проверку HTML5. В версиях Angular 4+ директива novalidate добавляется автоматически.

Давайте рассмотрим этот код подробнее:

  • formGroup: эта директива позволяет указать имя группы форм (поскольку форма будет рассматриваться как FormGroup в классе компонента).
  • ngSubmit: это событие запускается при отправке формы.
  • formControlName: такую директиву должно содержать каждое поле формы; в качестве значения formControlName будет указано имя, используемое в классе компонента.

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

3: Сборка класса компонента

Далее мы определим FormGroup и индивидуальные значения FormControl в классе компонента.

Если значение задается при создании FormControl, оно будет использоваться в качестве исходного значения поля.

Заметьте: имена FormGroup и FormControl совпадают с именами, использованными в шаблоне. Также обратите внимание, как вы инициализируете FormGroup в хуке жизненного цикла ngOnInit. Откройте файл src/app/app.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] })
export class AppComponent implements OnInit {
myForm: FormGroup;

ngOnInit() {


this.myForm = new FormGroup({


name: new FormControl('8host'),


email: new FormControl(''),


message: new FormControl('')


});


}


onSubmit(form: FormGroup) {


console.log('Valid?', form.valid); // true or false


console.log('Name', form.value.name);


console.log('Email', form.value.email);


console.log('Message', form.value.message);


}

}

Читайте также: Что такое хуки жизненного цикла в Angular

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

Итак, вы уже можете скомпилировать свое приложение и открыть его в веб-браузере. Попробуйте заполнить поля name, email и message и нажать Submit, чтобы убедиться, что эти значения отображаются в консоли.

4: Добавление класса FormBuilder

Конструкцию формы ngOnInit можно переписать с помощью FormBuilder. Это вспомогательный класс, который позволяет избежать создания FormControl и FormGroup.

Вернитесь в файл app.component.ts, удалите FormControl и замените FormGroup на FormBuilder:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] })
export class AppComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({

name: '8host',


email: '',


message: ''


});

}
onSubmit(form: FormGroup) {
console.log('Valid?', form.valid); // true or false
console.log('Name', form.value.name);
console.log('Email', form.value.email);
console.log('Message', form.value.message);
}
}

Как видите, класс FormBuilder сокращает объем стандартного кода для создания FormGroup.

5: Добавление класса Validators

Теперь добавьте класс Validators в импорт и объявите элементы FormControl через массивы, а не простые строковые значения.

Первое значение в массиве – это исходное значение формы, а второе – для валидаторов. Обратите внимание: в одном элементе FormControl можно использовать несколько валидаторов, заключив их в массив.

Вернитесь в файл app.component.ts в редакторе кода и добавьте Validators:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] })
export class AppComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
name: ['8host', Validators.required],
email: ['', [Validators.required, Validators.email]],
message: ['', [Validators.required, Validators.minLength(15)]],
});
}
onSubmit(form: FormGroup) {
console.log('Valid?', form.valid); // true or false
console.log('Name', form.value.name);
console.log('Email', form.value.email);
console.log('Message', form.value.message);
}
}

Этот код делает поля name, email и message обязательными к заполнению с помощью параметра required. Также он позволяет ввести только действительный адрес электронной почты и сообщение длиной не менее 15 символов.

Если какое-либо из этих требований к форме не выполняется, значение valid будет false; если же все требования к форме выполнены, значение valid будет true.

6: Доступ к данным формы в шаблоне

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

Давайте вернемся в редактор кода, где открыт файл app.component.html. Используйте *ngIf, чтобы обеспечить обратную связь с пользователем, если какие-либо введенные им значения будут недействительны:

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
<div>
<label>
Name:
<input formControlName="name" placeholder="Your name">
</label>
<div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)">
Please provide a name.
</div>
</div>
<div>
<label>
Email:
<input formControlName="email" placeholder="Your email">
</label>
<div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)">
Please provide a valid email address.
</div>
</div>
<div>
<label>
Message:
<input formControlName="message" placeholder="Your message">
</label>
<div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)">
Messages must be at least 15 characters long.
</div>
</div>
<button type="submit" [disabled]="myForm.invalid">Send</button>
</form>

Этот код проверяет, взаимодействовал ли пользователь с полем (dirty или touched). Далее, если значение не соответствует требованиям, пользователь увидит сообщение об ошибке. Кнопка Send будет отключена, пока пользователь не устранит все допущенные ошибки.

Существует несколько способов получить значения элементов FormControl. В этом примере используется myForm.get(‘name’), эквивалент myForm.controls.name. Информацию об ошибке можно получить с помощью .hasError(‘required’) или .errors.required.

Заключение

В этом мануале вы научились внедрять реактивные формы в приложения Angular. Здесь вы использовали классы FormControl, FormGroup, FormBuilder и Validators и в результате получили простую форму с проверкой. Чтобы узнать о дополнительных функциях форм в Angular, обратитесь к официальной документации проекта.

Tags: ,

Добавить комментарий