1. Валидация в Angular
Валидация — это процесс проверки данных, которые пользователь вводит в форму. Без неё любой сайт превращается в поле для экспериментов: кто-то забудет ввести имя, кто-то введёт email вида "я@непочта", а кто-то просто отправит пустую форму. Валидация защищает ваш интерфейс от ошибок пользователя (и иногда — от хакеров).
Angular поддерживает два подхода к валидации форм:
- Template-driven — валидация прямо в шаблоне с помощью HTML-атрибутов и Angular-директив.
- Reactive — валидация через объекты формы и валидаторы в TypeScript-коде (будет позже).
Сегодня мы работаем с первым вариантом — Template-driven.
Основные встроенные валидаторы
В Angular (и, на самом деле, в обычном HTML5) есть набор встроенных атрибутов-валидаторов, которые можно использовать прямо в шаблоне. Angular умеет их распознавать и автоматически следит за их выполнением.
Вот самые популярные:
| Атрибут | Проверяет |
|---|---|
|
Поле обязательно для заполнения |
|
Минимальная длина строки |
|
Максимальная длина строки |
|
Соответствие регулярному выражению |
|
Корректность email-адреса |
Давайте рассмотрим их по порядку на практике.
2. Практика: создаём форму с валидацией
Пример: Форма регистрации
<!-- registration.component.html -->
<form #regForm="ngForm" (ngSubmit)="onSubmit(regForm)">
<label>
Имя:
<input name="name" ngModel required minlength="2" #name="ngModel">
</label>
<div *ngIf="name.invalid && name.touched" style="color: red;">
<div *ngIf="name.errors?.required">Имя обязательно!</div>
<div *ngIf="name.errors?.minlength">Имя слишком короткое (минимум 2 символа).</div>
</div>
<label>
Email:
<input name="email" ngModel required email #email="ngModel">
</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 name="password" type="password" ngModel required minlength="6" maxlength="20" #password="ngModel">
</label>
<div *ngIf="password.invalid && password.touched" style="color: red;">
<div *ngIf="password.errors?.required">Пароль обязателен!</div>
<div *ngIf="password.errors?.minlength">Пароль слишком короткий (минимум 6 символов).</div>
<div *ngIf="password.errors?.maxlength">Пароль слишком длинный (максимум 20 символов).</div>
</div>
<label>
Телефон (только цифры, 10-12 символов):
<input name="phone" ngModel pattern="^[0-9]{10,12}$" #phone="ngModel">
</label>
<div *ngIf="phone.invalid && phone.touched" style="color: red;">
<div *ngIf="phone.errors?.pattern">Телефон должен содержать только цифры (10-12 символов).</div>
</div>
<button type="submit" [disabled]="regForm.invalid">Зарегистрироваться</button>
</form>
Разбор примера
- required — поле обязательно для заполнения. Если пользователь не ввёл имя/email/пароль — будет ошибка.
- minlength / maxlength — проверяют длину строки. Например, пароль должен быть не короче 6 и не длиннее 20 символов.
- email — Angular (и браузер) проверяет, что введённая строка похожа на email (есть «@», домен и т.д.).
- pattern — проверяет, что телефон состоит только из цифр и их 10-12.
Обратите внимание:
Каждое поле связано с локальной переменной шаблона (#name="ngModel", #email="ngModel", и т.д.), чтобы можно было проверить состояние поля: .invalid, .touched, .errors.
3. Как работает Angular-валидация под капотом?
Когда вы добавляете, например, required или minlength, Angular создаёт для поля объект валидатора и следит за его состоянием. Внутри Angular каждое поле формы — это объект с набором свойств:
- valid — все проверки пройдены.
- invalid — есть ошибки.
- touched — пользователь уже взаимодействовал с полем (например, кликнул и ушёл).
- dirty — пользователь изменил значение.
- errors — объект с ошибками (например, { required: true, minlength: { requiredLength: 2, actualLength: 1 } }).
С помощью этих свойств можно красиво показывать (или скрывать) ошибки.
Проверять ошибки лучше только после того, как пользователь начал что-то вводить (touched), чтобы не пугать его красной рамкой при первом открытии формы.
4. Разбираем каждый валидатор по отдельности
required
Пожалуй, самый важный валидатор. Если поле обязательно, просто добавьте атрибут required:
<input name="username" ngModel required #username="ngModel">
Angular не даст отправить форму, пока поле не заполнено. Ошибка будет доступна по username.errors?.required.
minlength & maxlength
Проверяют длину строки. Работают только для текстовых полей.
<input name="nick" ngModel required minlength="3" maxlength="12" #nick="ngModel">
Если пользователь введёт меньше 3 или больше 12 символов, свойство nick.invalid станет true, а в nick.errors появятся соответствующие поля.
pattern
Для проверки сложных правил используйте регулярные выражения.
<input name="zip" ngModel pattern="^[0-9]{6}$" #zip="ngModel">
Этот пример требует, чтобы индекс был из 6 цифр. Если не совпадает — zip.errors?.pattern будет true.
Совет:
Регулярки — штука мощная, но коварная. Проверяйте их в онлайн-сервисах типа regex101.com перед использованием.
Проверяет, что строка похожа на email. Это не полноценная проверка (например, не узнает, существует ли такой адрес), но защищает от явных опечаток.
<input name="userEmail" ngModel required email #userEmail="ngModel">
Если пользователь введёт "petya@", "test@123" или "abc", Angular покажет ошибку.
5. Полезные нюансы
Отображение ошибок пользователю
Показывать ошибки стоит только после того, как пользователь потрогал поле (touched или dirty). Это не только красиво, но и гуманно!
Пример для одного поля:
<input name="login" ngModel required minlength="4" #login="ngModel">
<div *ngIf="login.invalid && login.touched" style="color: red;">
<div *ngIf="login.errors?.required">Логин обязателен!</div>
<div *ngIf="login.errors?.minlength">
Логин слишком короткий (минимум {{login.errors.minlength.requiredLength}} символа).
</div>
</div>
Фишка:
login.errors.minlength.requiredLength — сколько символов требуется,
login.errors.minlength.actualLength — сколько ввёл пользователь.
Отключение кнопки "Отправить", если форма невалидна
Angular автоматически отслеживает валидность всей формы. В шаблоне можно сделать так:
<button type="submit" [disabled]="regForm.invalid">Отправить</button>
Пока хотя бы одно поле не прошло валидацию, кнопка будет неактивна.
Как получить доступ к ошибкам в TypeScript
Иногда нужно проверить валидность или ошибки в коде компонента:
// registration.component.ts
onSubmit(form: NgForm) {
if (form.invalid) {
// Можно показать alert или подсветить ошибки
alert('Форма заполнена с ошибками!');
return;
}
// Всё хорошо — можно отправлять данные
console.log('Данные формы:', form.value);
}
6. Практика: добавляем валидацию в учебное приложение
Давайте доработаем наше учебное приложение (например, регистрацию пользователя или добавление задачи в список дел).
Пример: Добавление задачи с валидацией
<!-- add-task.component.html -->
<form #taskForm="ngForm" (ngSubmit)="addTask(taskForm)">
<input name="task" ngModel required minlength="3" #task="ngModel" placeholder="Введите задачу">
<button type="submit" [disabled]="taskForm.invalid">Добавить</button>
<div *ngIf="task.invalid && task.touched" style="color: red;">
<div *ngIf="task.errors?.required">Пожалуйста, введите задачу!</div>
<div *ngIf="task.errors?.minlength">Минимум 3 символа.</div>
</div>
</form>
// add-task.component.ts
addTask(form: NgForm) {
if (form.invalid) return;
// Добавляем задачу в массив, очищаем форму и т.д.
}
7. Типичные ошибки при использовании встроенной валидации
Ошибка №1: Показывать ошибки до первого взаимодействия.
Если сразу отображать "Поля заполнены неверно!", пользователь испугается. Используйте touched или dirty для показа ошибок только после первого ввода.
Ошибка №2: Забыли объявить переменную шаблона (#field="ngModel").
Без неё нельзя проверить состояние поля и отобразить ошибки.
Ошибка №3: Слишком строгие/неочевидные паттерны.
Сложная регулярка может не пропускать валидные значения. Проверяйте паттерн вручную и объясняйте пользователю, что именно от него требуется.
Ошибка №4: Не отключили кнопку "Отправить" при невалидной форме.
Пользователь может отправить пустую или неверную форму, если не использовать [disabled]="form.invalid".
Ошибка №5: Валидация только на клиенте.
Не забывайте: любую валидацию можно обойти через консоль браузера! Проверяйте данные и на сервере.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ