Применение директивы 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" />
Перед тем как отправить форму, нам надо удостовериться, что данная форма содержит корректные значения. Для проверки используется механизм валидации. В 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",
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",
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 />
Хотя мы также можем задать регулярное выражение, как и в случае с полем для ввода телефона.