Применение директивы ngModel не только устанавливает привязку данных, но и позволяет отслеживать состояние элемента ввода. Для установки состояния Angular применяет к элементам ввода специальные классы CSS:
Если элемент ввода еще не получал фокус, то устанавливается класс ng-untouched. Если же поле ввода уже получало фокус, то к нему применяется класс ng-touched. При этом получение фокуса не обязательно должно сопровождаться изменением значения в этом поле.
Если первоначальное значение в поле ввода было изменено, то устанавливается класс ng-dirty. Если же значение не изменялось с момента загрузки страницы, то к элементу ввода применяется класс ng-pristine
Если значение в поле ввода корректно, то применяется класс ng-valid. Если же значение некорректно, то применяется класс ng-invalid
Например, при запуске веб-страницы для элемента ввода:
<input class="form-control" name="username" [(ngModel)]="username" />
Будет генерироваться следующая разметка html:
<input class="form-control ng-untouched ng-pristine ng-valid" name="username" ng-reflect-name="username" />
Перед тем как отправить форму, нам надо удостовериться, что данная форма содержит корректные значения. Для проверки используется механизм валидации. В Angular 2 мы можем использовать валидацию HTML5, которая применяется в виде атрибутов:
required: требует обязательного ввода значения
pattern: задает регулярное выражение, которому должны соответствовать вводимые данные
Для использования валидации определим следующий компонент:
import { Component} from "@angular/core"; import { FormsModule} from "@angular/forms"; class User{ constructor(public name: string, public email: string, public phone: string){} } @Component({ selector: "my-app", standalone: true, imports: [FormsModule], styles: ` .alert{ color:red} div {margin: 5px 0;} `, template: `<div> <div> <label>Имя</label><br> <input name="name" [(ngModel)]="user.name" #name="ngModel" required /> <div [hidden]="name.valid || name.untouched" class="alert"> Не указано имя </div> </div> <div> <label>Email</label><br> <input name="email" [(ngModel)]="user.email" #email="ngModel" required pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" /> <div [hidden]="email.valid || email.untouched" class="alert"> Некорректный email </div> </div> <div> <label>Телефон</label><br> <input name="phone" [(ngModel)]="user.phone" #phone="ngModel" required pattern="[0-9]{11}" /> <div [hidden]="phone.valid || phone.untouched" class="alert"> Некорректный телефон </div> </div> <button (click)="addUser()">Добавить</button> </div>` }) export class AppComponent { user: User = new User("", "", ""); addUser(){ console.log(this.user); } }
Для работы с данными определен класс User. Каждое поле ввода связано с определенным свойством объекта User. И также для каждого поля определены правила валидации в
виде атрибутов required
и pattern
. И рядом с каждым полем ввода определен специальный блок для вывода ошибки:
<div [hidden]="email.valid || email.untouched" class="alert"> Некорректный email </div>
Здесь проверяется валидность поля email. Для этого мы берем переменную email, которая представляет связанный с полем ввода объект NgModel
(#email="ngModel"
), и смотрим на свойства valid
и untouched
у этого объекта. Если хотя бы одно из этих свойств равно true,
то атрибут hidden
тоже равен true. А это значит, что блок div будет скрыт. То есть если поле для ввода email валидно, то блок скрывается. Иначе
мы видим сообщение об ошибке.
В принципе для проверки корректности нам достаточно посмотреть на свойство valid
. Однако не всегда может желательно сразу отображать ошибку
при загрузке страницы. В данном же случае мы смотрим на валидность, если поле ввода уже получало фокус.
Для стилизации сообщений об ошибках применяются классы bootstrap:
В то же время несмотря на наличие ошибок валидации мы можем нажать на кнопку и выполнить метод addUser()
, который обработает введенные данные.
Однако поскольку данные некорректны, любая обработка будет бессмысленной. И в этом случае можно отключить кнопку. Для этого опять же можно применить проверку
на валидность полей. Так, изменим код кнопки следующим образом:
<button [disabled]="name.invalid || email.invalid || phone.invalid" (click)="addUser()">Добавить</button>
С помощью выражения [disabled]="name.invalid || email.invalid || phone.invalid"
для атрибута disabled устанавливается значение true, то есть
кнопка отключается, если хотя бы одно из полей не валидно.
Выше применялись стили bootstrap для стилизации отображения ошибок. Однако используя классы ng-valid и ng-invalid, мы можем задать дополнительные возможности по стилизации. В частности, изменим компонент следующим образом:
import { Component} from "@angular/core"; import { FormsModule} from "@angular/forms"; class User{ constructor(public name: string, public email: string, public phone: string){} } @Component({ selector: "my-app", standalone: true, imports: [FormsModule], styles: ` .alert{ color:red} div {margin: 5px 0;} input.ng-touched.ng-invalid {border:solid red 2px;} input.ng-touched.ng-valid {border:solid green 2px;} `, template: `<div> <div> <label>Имя</label><br> <input name="name" [(ngModel)]="user.name" #name="ngModel" required /> </div> <div> <label>Email</label><br> <input name="email" type="email" [(ngModel)]="user.email" #email="ngModel" required email /> </div> <div> <label>Телефон</label><br> <input name="phone" [(ngModel)]="user.phone" #phone="ngModel" required pattern="[0-9]{11}" /> </div> <button [disabled]="name.invalid || email.invalid || phone.invalid" (click)="addUser()">Добавить</button> </div>` }) export class AppComponent { user: User = new User("", "", ""); addUser(){ console.log(this.user); } }
Для валидации email применяется специальный валидатор email
<input type="email" name="email" [(ngModel)]="user.email" #email="ngModel" required email />
Хотя мы также можем задать регулярное выражение, как и в случае с полем для ввода телефона.