Проверка данных формы
Проверка (валидация) не даёт отправить форму с пустыми или неправильными данными и подсказывает пользователю, что исправить. В реактивных формах правила задаются в классе вместе с полями, а шаблон показывает сообщения.
Встроенные валидаторы
Правила передают вторым аргументом FormControl в массиве validators:
// src/app/post-form/post-form.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
@Component({
selector: 'app-post-form',
imports: [ReactiveFormsModule],
templateUrl: './post-form.html',
})
export class PostForm {
form = new FormGroup({
title: new FormControl('', {
nonNullable: true,
validators: [Validators.required, Validators.minLength(5)],
}),
body: new FormControl('', {
nonNullable: true,
validators: [Validators.required],
}),
});
}Заголовок обязателен и не короче пяти символов, текст обязателен.
| Валидатор | Правило |
|---|---|
Validators.required | Поле не пустое |
Validators.minLength(5) | Не меньше 5 символов |
Validators.maxLength(100) | Не больше 100 символов |
Validators.email | Похоже на адрес почты |
Validators.min(1), Validators.max(10) | Число в пределах |
Validators.pattern(/^[a-z]+$/) | Соответствует регулярному выражению |
Сообщения об ошибках
У каждого поля есть свойства состояния. invalid — правило нарушено, touched — пользователь уже побывал в поле. Метод hasError() проверяет конкретное правило:
<!-- src/app/post-form/post-form.html -->
<form [formGroup]="form" (ngSubmit)="save()">
<input formControlName="title" placeholder="Заголовок" />
@let title = form.controls.title;
@if (title.touched && title.hasError('required')) {
<p class="error">Введите заголовок.</p>
}
@if (title.touched && title.hasError('minlength')) {
<p class="error">Не короче 5 символов.</p>
}
<textarea formControlName="body" placeholder="Текст"></textarea>
<button type="submit" [disabled]="form.invalid">Опубликовать</button>
</form>Блок @let объявляет короткое имя прямо в шаблоне. Щёлкните в поле заголовка и уйдите из него — появится «Введите заголовок.». Наберите «Тест» — сообщение сменится на «Не короче 5 символов.». Кнопка остаётся заблокированной, пока форма неверна.
CSS-классы состояния
Angular сам добавляет полям классы ng-valid, ng-invalid, ng-touched, ng-dirty. Красная рамка у ошибочного поля делается без кода:
/* src/app/post-form/post-form.css */
input.ng-invalid.ng-touched,
textarea.ng-invalid.ng-touched {
border: 1px solid crimson;
}Проверка при отправке
Если кнопку не блокировать, проверьте форму в методе и подсветите все ошибки сразу:
// src/app/post-form/post-form.ts
save() {
if (this.form.invalid) {
this.form.markAllAsTouched();
return;
}
console.log('Отправляем', this.form.getRawValue());
}markAllAsTouched() помечает все поля как посещённые, и сообщения появляются у каждого неверного поля.
Свой валидатор
Валидатор — функция, которая получает поле и возвращает null, если всё в порядке, или объект с описанием ошибки:
// src/app/no-spam.ts
import { AbstractControl, ValidationErrors } from '@angular/forms';
export function noSpam(control: AbstractControl): ValidationErrors | null {
const text = String(control.value).toLowerCase();
return text.includes('casino') ? { spam: true } : null;
}Подключите его как встроенный: validators: [Validators.required, noSpam], а в шаблоне проверяйте hasError('spam').
Частая ошибка
Показывать ошибки сразу при открытии формы. Пустое обязательное поле неверно с самого начала, и пользователь видит красный текст, ещё ничего не сделав. Добавляйте к условию touched или dirty, как в примере выше.