Angular предоставляет два способа работы с формами: шаблонные формы и реактивные формы, последние еще называют формами управляемые моделью. Шаблонные формы используются по умолчанию в Angular для работы с формами, директивы в шаблонах используются для построения внутреннего представления формы. В реактивных формах вы создаете собственное представления формы в классе компоненте.
Хотя реактивные формы могут показаться сложными при начале работы с ними, они позволяют сделать формы более гибкими и помогают держать логику внутри класса компонента и делают шаблоны более простыми.
Примеры случаев где реактивные формы очень удобны:
- написания кастомных валидаторов
- динамическое изменение валидации
- динамическое добавления элементов формы
Давайте рассмотрим как интегрировать реактивные формы в ваше Angular приложение.
Импорт модуля ReactiveFormsModule
Для работы с реактивными формами, мы будем использовать модуль ReactiveFormsModule вместо FormsModule.
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AppComponent } from './app.component'; @NgModule({ // ... imports: [ BrowserModule, ReactiveFormsModule, HttpModule ], // ... }) export class AppModule { }
Пример шаблона: formGroup, ngSubmit & formControlName
При использовании реактивных форм вся логика содержится в классе компонента, поэтому код шаблона выглядит очень простым:
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)"> <input formControlName="login" placeholder="Your email"> <input type="password" formControlName="password" placeholder="Your password"> <button type="submit">Submit</button> </form>
Если вы используете Angular 2.x, добавьте директиву novalidate в тег формы, так как Angular переопределять HTML5 валидацию. В Angular 4+ директива novalidate добавляет автоматически.
Рассмотрим директивы formGroup, ngSubmit & formControlName детальней
- formGroup — форма будет трактоваться как FormGroup в классе компоненте. Директива formGroup позволяет дать имя форме.
- ngSubmit: Позволяет зарегистрировать обработчик сабмита формы
- formControlName: Каждое поле формы должно иметь директиву formControlName с значением имени, которое будет
использоваться в классе компоненте
Класс компонент
В классе компоненте мы определим группу формы и каждое поле в нашей группе.
При создании FormControl можно задать начальное значения поля.
Обратите внимания как имена группы формы и имена полей совпадают с теми которые мы использовали в шаблоне. Также необходимо инициализировать форму в методе жизненного цикла ngOnInit
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Component({ // ... }) export class AppComponent implements OnInit { myForm: FormGroup; ngOnInit() { this.myForm = new FormGroup({ login: new FormControl(''), password: new FormControl('') }); } onSubmit(form: FormGroup) { console.log('Valid?', form.valid); // true or false console.log('Login', form.value.login); console.log('Password', form.value.password); } }
FormBuilder
Мы можем упростить код с помощью класса FormBuilder, который позволяет нам отказаться от ручного создания элементов FormControl и FormGroup.
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; @Component({ // ... }) export class AppComponent implements OnInit { myForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.myForm = this.fb.group({ login: '', password: '' }); } // ... }
Валидация
Добавления валидации в форму происходит очень просто. Нужно импортировать класс Validators и передать массив как начальное значения поля формы.
Первое значения в массиве отвечает за начальное значения поля второе отвечает за валидаторы. Кроме того можно передать несколько валидаторов.
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ // ... }) export class AppComponent implements OnInit { myForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.myForm = this.fb.group({ login: ['', [Validators.required, Validators.pattern('[a-z0-9.@]*')]], password: ['', [Validators.required, Validators.minLength(6)]] }); } }
Получения доступа к значения элементов формы и их валидности в шаблоне
В шаблоне формы мы можем получить доступ к каждому элементу формы и состоянию их валидности, а также валидности всей группы
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)"> <input formControlName="login" placeholder="Your login"> <p>Your login: {{ myForm.get('login').value }}</p> <div *ngIf="myForm.get('login').hasError('required')"> Oops, please provide a login! </div> <input formControlName="password" placeholder="Your password"> <div *ngIf="myForm.controls.email.hasError('minLength')"> Oops, password too short! </div> <button type="submit" [disabled]="myForm.invalid"> Send </button> </form>
Обратите внимания на то как можно получить доступ как с myForm.get(‘login’) так и myForm.controls.login, также мы можем получить доступ к ошибкам с помощью .hasError(‘required’) или .errors.required. Оба способы аналогичны и это дела вкуса что использовать
Также мы делаем кнопку отправки формы неактивной если форма не валидна.
Заключения
В этой статье сделано введения по работе с реактивными формами в Angular, более детальное описания можно найти в официальной документации. https://angular.io/docs/ts/latest/guide/reactive-forms.html