Оглавление:
Карта сайта:
Оглавление:
Карта сайта:
В прошлых темах был описан подход Template-Driven, который концентрировался вокруг шаблона компонента: для работы с формой и ее элементами в шаблоне компонента к элементам html применялись директивы NgModel и NgForm, правила валидации задавались в тегах элементов с помощью атрибутов required и pattern. Но есть альтернативный подход - использование реактивных форм (Reactive Forms). Рассмотрим, в чем он заключается.
При подходе Reactive Forms для формы создается набор объектов FormGroup и FormControl. Сама форма и ее подсекции представляют класс FormGroup, а отдельные элементы ввода - класс FormControl. Например, базовое создание формы:
this.form = new FormGroup();
Добавляем в форму элементы:
this.form = new FormGroup( { email: new FormControl(), pass: new FormControl(), country: new FormControl(), answer: new FormControl() } );
Здесь определено четыре элемента: email, pass, country и userPhone.\
Объект FormControl может иметь различные формы определения. (Подробнее можно посмотреть в документации). В частности, в качестве первого параметра можно передавать значение по умолчанию для элемента, а в качестве второго параметра - набор валидаторов, при этом элементы формы можно группировать с помощью FormGroup:
ngOnInit() { this.form = new FormGroup( { user: new FormGroup({ email: new FormControl('anchikin@mail.ru', [Validators.email, Validators.required]), pass: new FormControl('', Validators.required), }), country: new FormControl('ru'), answer: new FormControl('no') } ); }
Здесь к элементам применяется ряд валидаторов. Валидатор Validators.required требует обязательного наличия значения. Валидатор Validators.email проверяет, представляет ли введенная строка электронный адрес. Валидатор Validators.pattern(«[0-9]{10}») поверяет на соответствие регулярному выражению. Все встроенные валидаторы можно посмотреть в документации. Если валидаторов несколько, то они заключаются в массив.
Для привязки объекта myForm к конкретному элементу формы применяется атрибут formGroup:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
Кроме того, необходимо связать объекты FormControl с элементами ввода с помощью атрибута formControlName:
<input type="text" class="form-control" formControlName="email">
Данный элемент будет связан с объектом «email»: new FormControl('anchikin@mail.ru', [Validators.email, Validators.required]).
Теперь рассмотрим, как эти объекты будут взаимодействовать с шаблоном компонента. Для этого определим следующий компонент:
import { Component, OnInit } from '@angular/core'; import {FormControl, FormGroup, Validators} from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { answers = [{ type: 'yes', text: 'Да' }, { type: 'no', text: 'Нет' }]; form: any; ngOnInit() { this.form = new FormGroup( { user: new FormGroup({ email: new FormControl('anchikin@mail.ru', [Validators.email, Validators.required]), pass: new FormControl('', Validators.required), }), country: new FormControl('ru'), answer: new FormControl('no') } ); } onSubmit() { console.log('Submited!', this.form); } }
<div class="col-xs-8 col-xs-offset-2"> <form [formGroup]="form" (ngSubmit)="onSubmit()"> <div formGroupName="user"> <div class="form-group" [ngClass]="{'has-error': form.get('user.email').invalid && form.get('user.email').touched}"> <label>Email</label> <input type="text" class="form-control" formControlName="email"> <p class="help-block" *ngIf="form.get('user.email').invalid && form.get('user.email').touched">Не правильно прописан email</p> </div> <div class="form-group" [ngClass]="{'has-error': form.get('user.pass').invalid && form.get('user.pass').touched}"> <label>Пароль</label> <input type="password" class="form-control" formControlName="pass"> <p class="help-block" *ngIf="form.get('user.pass').invalid && form.get('user.pass').touched">пароль не должен быть пустым!</p> </div> </div> <div class="form-group"> <label>Выберите страну</label> <select class="form-control" formControlName="country"> <option value="ru">Россия</option> <option value="by">Белоруссия</option> <option value="ua">Украина</option> </select> </div> <div class="radio" *ngFor="let ans of answers"> <label> <input type="radio" name="answer" formControlName="answer" [value]="ans.type" > {{ans.text}} </label> </div> <button [disabled]="form.invalid" class="btn btn-success" type="submit">Сохранить</button> </form> </div>
Для отображения ошибок валидации здесь используется параграфы с классом help-block, в которых определены выражения типа
<p class="help-block" *ngIf="form.get('user.email').invalid && form.get('user.email').touched">Не правильно прописан email</p>
С помощью выражений form.controls['user.email'] или form.get('user.email') мы можем обратиться к нужному элементу формы и получить его состояние или значение. В данном случае если значение поля ввода невалидно, и при этом поле ввода уже получало фокус, то отображается ошибка валидации.
Но чтобы все это заработало, необходимо импортировать модуль ReactiveFormsModule. Для этого изменим модуль приложения AppModule:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, ReactiveFormsModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }