1. Введение
Представьте себе интернет-магазин, где можно оформить заказ, указав e-mail "котик", а телефон — "много восьмерок и пару смайликов". Как думаете, как быстро владельцы магазина начнут искать нового программиста? Валидация — это тот самый невидимый "охранник", который не пропустит в систему неправильные данные.
Angular даёт нам мощный инструментарий для валидации форм. Сегодня мы рассмотрим три самых популярных (и полезных!) валидатора:
- Validators.required — поле обязательно для заполнения.
- Validators.email — поле должно содержать валидный email.
- Validators.minLength — минимальная длина строки.
Давайте разберёмся, как они работают и как их подключать на практике.
Как добавить валидаторы к полям формы?
Всё очень просто: валидаторы подключаются прямо при создании FormControl. Можно передать их в конструктор вторым аргументом, а если их несколько — использовать массив.
Пример: минимальная форма с валидаторами
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-register-form',
template: `
<form [formGroup]="registerForm">
<input formControlName="email" placeholder="Email">
<input formControlName="password" placeholder="Пароль" type="password">
<button>Зарегистрироваться</button>
</form>
`
})
export class RegisterFormComponent {
registerForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(6)])
});
}
Что здесь происходит:
— Для поля email мы требуем обязательное заполнение (Validators.required) и корректный формат email (Validators.email).
— Для поля password — обязательно и минимум 6 символов (Validators.minLength(6)).
2. Проверяем статус валидации в шаблоне
Валидаторы сами по себе — это как строгий учитель, который молча ставит двойки. Но пользователю нужно объяснить, что он сделал не так! Для этого мы можем проверить состояние поля и показать подсказку.
Пример: выводим ошибки под полями
<form [formGroup]="registerForm">
<label>
Email:
<input formControlName="email">
</label>
<div *ngIf="email.invalid && email.touched" style="color: red;">
<div *ngIf="email.errors?.['required']">Email обязателен!</div>
<div *ngIf="email.errors?.['email']">Введите корректный email.</div>
</div>
<label>
Пароль:
<input type="password" formControlName="password">
</label>
<div *ngIf="password.invalid && password.touched" style="color: red;">
<div *ngIf="password.errors?.['required']">Пароль обязателен!</div>
<div *ngIf="password.errors?.['minlength']">
Пароль должен быть не короче {{ password.errors?.['minlength'].requiredLength }} символов.
Сейчас: {{ password.errors?.['minlength'].actualLength }}
</div>
</div>
<button [disabled]="registerForm.invalid">Зарегистрироваться</button>
</form>
А в компоненте:
get email() {
return this.registerForm.get('email')!;
}
get password() {
return this.registerForm.get('password')!;
}
Пояснения:
— email.invalid && email.touched — показываем ошибку только если поле уже трогали (а не сразу при загрузке).
— email.errors?.['required'] — Angular кладёт ошибки в объект errors по ключу названия валидатора.
— Для minlength можно вывести, сколько символов не хватает.
3. Как работают валидаторы под капотом?
Каждый валидатор — это просто функция, которая проверяет значение и возвращает либо null (если всё хорошо), либо объект с ошибкой. Angular уже реализовал самые частые проверки за нас.
Вот, например, как выглядит Validators.required (упрощённо):
static required(control: AbstractControl): ValidationErrors | null {
return control.value == null || control.value === ''
? { 'required': true }
: null;
}
Если поле пустое — возвращает ошибку, иначе всё ок.
Как Angular узнаёт, что поле невалидно?
- Каждый FormControl хранит свойство .valid (всё ок) и .invalid (что-то не так).
- Ошибки доступны через .errors.
- FormGroup становится невалидной, если хотя бы одно поле не проходит валидацию.
4. Полезные нюансы
Validators.required — обязательное поле
Это самый частый валидатор: запрещает отправлять форму, если поле пустое. Работает для строк, чисел, даже чекбоксов.
Примеры:
new FormControl('', Validators.required); // строка
new FormControl(false, Validators.required); // чекбокс
Если поле пустое ('', null, undefined, false для чекбокса) — будет ошибка 'required': true.
В шаблоне:
<div *ngIf="control.errors?.['required']">Поле обязательно для заполнения!</div>
Validators.email — проверка email
Проверяет, что значение похоже на email. Не ждите, что он проверит, существует ли такой ящик — только что строка похожа на "что-то@что-то.что-то".
Пример:
new FormControl('', [Validators.required, Validators.email]);
Если строка не подходит под email-паттерн — ошибка 'email': true.
В шаблоне:
<div *ngIf="control.errors?.['email']">Введите корректный email.</div>
Важно:
Этот валидатор не проверяет, что email реально существует, а только что написан по правилам.
Validators.minLength — минимальная длина
Ограничивает минимальное количество символов, которые пользователь должен ввести.
Пример:
new FormControl('', [Validators.required, Validators.minLength(8)]);
Если длина строки меньше 8 — ошибка 'minlength': { requiredLength: 8, actualLength: ... }
В шаблоне:
<div *ngIf="control.errors?.['minlength']">
Минимальная длина — {{ control.errors?.['minlength'].requiredLength }} символов.
Сейчас: {{ control.errors?.['minlength'].actualLength }}
</div>
Комбинирование валидаторов
Можно передать массив валидаторов, и Angular будет проверять их все:
new FormControl('', [
Validators.required,
Validators.email,
Validators.minLength(10)
]);
Ошибки будут складываться в объект errors с соответствующими ключами.
Проверка валидности формы и её отправка
Обычно кнопку "Отправить" блокируют, если форма невалидна:
<button [disabled]="registerForm.invalid">Зарегистрироваться</button>
В методе отправки формы можно проверить:
onSubmit() {
if (this.registerForm.invalid) {
// Можно подсветить все поля
this.registerForm.markAllAsTouched();
return;
}
// Всё ок — отправляем данные!
console.log(this.registerForm.value);
}
Таблица: основные встроенные валидаторы
| Валидатор | Описание | Ошибка в errors | Пример использования |
|---|---|---|---|
|
Обязательное поле | |
|
|
Корректный email | |
|
|
Минимальная длина строки | |
|
|
Максимальная длина строки | |
|
|
Проверка по регулярному выражению | |
|
5. Практический пример: форма регистрации
Давайте соберём всё вместе.
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-register-form',
template: `
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
<label>
Email:
<input formControlName="email">
</label>
<div *ngIf="email.invalid && email.touched" class="error">
<div *ngIf="email.errors?.['required']">Email обязателен!</div>
<div *ngIf="email.errors?.['email']">Некорректный email.</div>
</div>
<label>
Пароль:
<input type="password" formControlName="password">
</label>
<div *ngIf="password.invalid && password.touched" class="error">
<div *ngIf="password.errors?.['required']">Пароль обязателен!</div>
<div *ngIf="password.errors?.['minlength']">
Минимум {{ password.errors?.['minlength'].requiredLength }} символов.
Сейчас: {{ password.errors?.['minlength'].actualLength }}
</div>
</div>
<button [disabled]="registerForm.invalid">Зарегистрироваться</button>
</form>
`,
styles: [`
.error { color: red; font-size: 0.9em; }
input.ng-touched.ng-invalid { border: 1px solid red; }
`]
})
export class RegisterFormComponent {
registerForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(6)])
});
get email() { return this.registerForm.get('email')!; }
get password() { return this.registerForm.get('password')!; }
onSubmit() {
if (this.registerForm.invalid) {
this.registerForm.markAllAsTouched();
return;
}
alert('Регистрация прошла успешно! Данные: ' + JSON.stringify(this.registerForm.value));
// Здесь можно отправить данные на сервер
}
}
6. Типичные ошибки при использовании валидаторов
Ошибка №1: Не показывают ошибки, пока пользователь не тронул поле.
Пользователь думает, что всё хорошо, а при отправке формы — сюрприз. Используйте свойство .touched или .dirty, чтобы ошибки появлялись только когда поле реально трогали.
Ошибка №2: Проверяют только .invalid без уточнения типа ошибки.
Если у поля несколько валидаторов, важно показывать конкретную ошибку, а не просто "Что-то не так".
Ошибка №3: Не вызывают .markAllAsTouched() при отправке формы.
Если пользователь сразу жмёт "Отправить", а поля не тронуты — ошибки не появятся. Вызовите markAllAsTouched(), чтобы подсветить всё.
Ошибка №4: Используют только Validators.required, забывая про формат.
Например, для email — обязательно добавляйте Validators.email, иначе "qwerty" пройдёт проверку.
Ошибка №5: Не блокируют кнопку, когда форма невалидна.
Пользователь может отправить пустую форму — и вы получите кучу пустых заявок. Всегда делайте [disabled]="form.invalid".
Ошибка №6: Слишком много проверок в шаблоне.
Лучше вынести доступ к контролам в геттеры компонента, чтобы не писать длинные выражения в шаблоне.
Ошибка №7: Не обновляют ошибки после программного изменения значений.
Если вы меняете значения формы в коде, иногда нужно вызвать updateValueAndValidity() для пересчёта ошибок.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ