Формы. Шаблонный подход.
Создание формы и регистрация контроллеров
Для работы с формами нужно добавить FormsModule
в импорты модуля. Аpp.modules.ts
:
//...
import { FormsModule } from '@angular/forms';
//...
@NgModule({
//...
imports: [
//...
FormsModule,
],
//...
Добавить директиву ngModel
в input
и select
формы, чтобы указать, что данный инпут это контроллер формы:
<input
type="text"
id="username"
class="form-control"
name="username"
ngModel
>
Чтобы использовать директиву ngModel
у поля обязательно должен быть указан атрибут name
. Иначе в консоли будет ошибка.
Для назначения обработчика используется событие ngSubmit
:
<form (ngSubmit)="onSubmit()">
Для того, чтобы передать в обработчик данные формы можно использовать локальную ссылку #:
<form (ngSubmit)="onSubmit(formdata)" #formdata>
Чтобы передать в обработчик не просто локальную ссылку, а js объект, представляющий данные формы и связанный с ней, нужно воспользоваться директивой NgForm
:
<form (ngSubmit)="onSubmit(formdata)" #formdata="ngForm">
Доступ к форме с помощью @ViewChild
Если нужно получить данные формы до момента отправки, то можно воспользоваться @ViewChild
.
Шаблон:
<form (ngSubmit)="onSubmit()" #formdata="ngForm">
Компонент:
import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
@Component({
//...
})
export class AppComponent {
@ViewChild('formdata') myForm: NgForm;
//...
onSubmit(form: NgForm) {
console.log(this.myForm);
}
}
Валидация форм
Angular поддерживает специальные директивы, позволяющие валидировать пользовательский ввод.
required
- обязательное для заполнения полеemail
- указатель, что поле формата email адрес.
Пример использования данных директив:
<input
type="email"
id="email"
class="form-control"
name="email"
ngModel
required
email
>
Angular динамически устанавливает css классы у проверяемых инпутов. Это позволяет создавать дизайн для различных состояний.
Список встроенных валидаторов.
ngNativeValidate
(добавляется в поле шаблона) - директива переключает Angular в режим стандартной HTML5 валидации.
Валидация регулярным выражением
В input
шаблона добавить паттерн регулярного выражения, например: [pattern]="'^[1-9][0-9]*$'"
.
Или короткий вариант записи: pattern="^[1-9][0-9]*$"
.
Использование состояний формы
Скрытие кнопки, если форма не прошла валидацию:
<form (ngSubmit)="onSubmit(formdata)" #formdata="ngForm">
<button
class="btn btn-primary"
type="submit"
[disabled]="!formdata.valid"
>
Submit
</button>
</form>
Выделение инпута красной рамкой. В стилях шаблона:
input.ng-invalid.ng-touched {
border: 1px solid red;
}
Вывод ошибок валидации
<input
type="email"
id="email"
class="form-control"
name="email"
ngModel
required
email
#email="ngModel"
>
<span *ngIf="!email.valid && email.touched">
Enter valid email
</span>
Значение по умолчанию
С помощью [ngModel]="'value_name'"
можно установить дефолтное значение. Если используется значение переменной компонента, то вторые кавычки не нужны: [ngModel]="value_name_from_component"
.
<select
id="secret"
class="form-control"
name="secret"
[ngModel]="'teacher'"
>
<option value="pet">Your first Pet?</option>
<option value="teacher">Your first teacher?</option>
</select>
ngModel и двухстороннее связывание
<div class="form-group">
<textarea
name="questionAnswer"
rows="3"
class="form-control"
[(ngModel)]="answer"
>
</textarea>
<p>You type: {{answer}}</p>
</div>
Переменная answer
должна быть определена в компоненте.
Группировка элементов
Несколько элементов могут быть сгруппированы с помощью директивы ngModelGroup
. Для этого нужно обернуть div'ом несколько элементов формы и указать у данного блока эту директиву.
Локальная ссылка создается по шаблону #link_name="ngModelGroup"
. Это позволяет получить доступ к js объекту.
Сгруппировав несколько элементов формы и создав локальную ссылку, мы можем использовать js объект для различных целей, например, для вывода предупреждения о том, что какой-либо элемент группы не прошел валидацию:
<p *ngIf="!link_name.valid && link_name.touched">
Не верно заполнена группа
</p>
Радиокнопки (Radiobuttons)
В компоненте создадим переменную:
genders = ['male', 'female'];
В шаблоне:
<div class="radio" *ngFor="let gender of genders">
<label>
<input
type="radio"
name="gender"
ngModel
[value]="gender"
required
>
{{gender}}
</label>
</div>
Установка значения формы из компонента
У NgForm
есть метод setValue()
, который принимает значения всех полей формы и устанавливает их:
@ViewChild('formdata') myForm: NgForm;
//...
suggestUserName() {
const suggestedName = 'Superuser';
this.myForm.setValue({
username: suggestedName,
email: '',
secret: 'pet',
questionAnswer: '',
gender: 'male',
});
}
Чтобы изменить не все поля формы, а только часть, используется другой метод:
@ViewChild('formdata') myForm: NgForm;
//...
this.myForm.form.patchValue({
username: suggestedName,
gender: 'male',
});
Использование данных формы
Создадим объект user
и запишем в него данные формы, на событие отправки формы.
user = {
name: '',
mail: '',
secretQuestion: '',
answer: '',
gender: '',
}
onSubmit() {
this.submitted = true;
this.user.name = this.myForm.value.username;
this.user.mail = this.myForm.value.email;
this.user.secretQuestion = this.myForm.value.secret;
this.user.answer = this.myForm.value.questionAnswer;
this.user.gender = this.myForm.value.gender;
}
Если данные в форме сгруппированы, то необходимо указывать группу, например:
this.user.name = this.myForm.value.userData.username;
this.user.mail = this.myForm.value.userData.email;
Сброс формы
@ViewChild('formdata') myForm: NgForm;
//...
this.myForm.reset();
В функцию reset()
можно передать объект, аналогичный тому, который передается в setValue()
, чтобы сбросить поля в определенные значения.