Пользовательские валидаторы форм в Angular
Development, Java | Комментировать запись
Валидаторы используются для обеспечения соответствия значений в форме определенным требованиям. В приложениях Angular они поддерживаются шаблонными и реактивными формами.
Читайте также: Введение в реактивные формы Angular
Существует несколько встроенных валидаторов Angular: это required, email, pattern и minLength. А для работы с функциями, которые не поддерживаются встроенными валидаторами, вы можете разработать собственные, пользовательские валидаторы.
Например, валидатор для телефонного номера – это поле ввода, которое подсвечивается красным (следовательно, не считается действительным), если указанное значение содержит менее десяти цифр. Такой валидатор мог бы выдавать предупреждение или подсказку в случае неприемлемого значения, к примеру: «Phone number must be of 10 digits».
В этом руководстве мы создадим такой пользовательский валидатор для поля ввода номера телефона в приложении Angular.
Требования
Для выполнения этого урока вам понадобится:
- Локальная установка Node.js. Следуйте инструкциям для вашего дистрибутива: mac OS, Ubuntu, Debian, CentOS.
- Базовое знакомство с настройкой проекта Angular.
Это руководство было проверено на версиях Node v15.2.1, npm v6.14.8, @angular/core v11.0.0 и @angular/forms v11.0.0.
Настройка проекта
В рамках этого руководства мы создадим простой проект на основе стандартного проекта Angular, созданного с помощью @angular/cli.
npx @angular/cli new angular-custom-validation-example --style=css --routing=false --skip-tests
Примечание: В качестве альтернативы вы можете установить @angular/cli глобально.
Эта команда настроит новый проект Angular со стилями CSS (также доступны Sass, Less или Stylus), без маршрутизации и тестирования.
Перейдите во только что созданный каталог проекта:
cd angular-custom-validation-example
На этом этапе у нас готов новый проект Angular.
Валидаторы в шаблонных формах
В качестве валидаторов в шаблонных формах используются директивы. В этом примере мы создадим директиву phone-number-validator с помощью @angular/cli.
Сначала откройте свой терминал и используйте пакет @angular/cli, который был установлен как зависимость разработки. Он нужен нам для создания новой директивы:
./node_modules/@angular/cli/bin/ng generate directive phone-number-validator
Эта команда создаст phone-number-validator.directive.ts и phone-number-validator.directive.spec.ts. Она также добавит PhoneNumberValidatorDirective в файл app.module.ts.
Затем откройте в редакторе кода файл phone-number-validator.directive.ts. Добавьте в него Validator, AbstractControl и NG_VALIDATORS:
import { Directive } from '@angular/core';
import { AbstractControl, Validator, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[appPhoneNumberValidator]',
providers: [{
provide: NG_VALIDATORS,
useExisting: PhoneNumberValidatorDirective,
multi: true
}]
})
export class PhoneNumberValidatorDirective implements Validator {
validate(control: AbstractControl) : {[key: string]: any} | null {
if (control.value && control.value.length != 10) {
return { 'phoneNumberInvalid': true };
}
return null;
}
}
Этот код создает директиву, которая реализует Validator для @angular/forms. Для этой реализации потребуется следующий метод:
validate(control: AbstractControl): : {[key: string]: any} | null
Этот валидатор вернет объект – { ‘phoneNumberInvalid’: true } – если значение не соответствует заданному условию (то есть, если оно включает в себя менее 10 символов). В противном случае, если значение соответствует условию, валидатор вернет null.
Затем откройте свой терминал и используйте пакет @angular/cli, который был установлен как зависимость разработки, для создания новой директивы:
./node_modules/@angular/cli/bin/ng generate component template-driven-form-example --flat
Эта команда создаст файлы template-driven-form-example.component.ts и template-driven-form-example.component.html . Она также добавит TemplateDrivenFormExampleComponent в файл app.module.ts.
Затем откройте template-driven-form-example.component.ts в редакторе кода и добавьте phone с пустой строкой в качестве начального значения.
import { Component } from '@angular/core';
@Component({
selector: 'app-template-driven-form-example',
templateUrl: './template-driven-form-example.component.html',
styleUrls: ['./template-driven-form-example.component.css']
})
export class TemplateDrivenFormExampleComponent {
phone = '';
}
Angular добавляет возвращаемое значение валидатора в свойство errors в FormControl / NgModel. Если это свойство не пусто, форма считается недействительной. Если же оно пусто, значит форма проходит проверку.
Чтобы использовать директиву в шаблонной форме, откройте простую шаблонную форму example.component.html и добавьте следующий код:
<div class="form-group"> <label>Phone <input type="text" class="form-control" name="phone" [(ngModel)]="phone" #phoneNgModel="ngModel" appPhoneNumberValidator [class.is-invalid]="(phoneNgModel.touched || phoneNgModel.dirty) && phoneNgModel.errors?.phoneNumberInvalid" > </label> <span class="invalid-feedback" *ngIf="(phoneNgModel.touched || phoneNgModel.dirty) && phoneNgModel.errors?.phoneNumberInvalid" > Phone number must be 10 digits </span> </div>
Этот код создает элемент <input> и <span> с сообщением об ошибке. Элемент <input> использует ngModel и селектор appPhoneNumberValidator для директивы.
Если <input> получил значение touched или dirty и форма не проходит проверку, произойдут две вещи. Во-первых, к <input> будет применен класс is-invalid. Во-вторых, на экране отобразится <span> с сообщением об ошибке.
Примечание: Некоторые из этих классов – form-group, form-control, invalid-feedback и is-valid – являются частью Bootstrap Framework. Они не нужны для выполнения данного руководства, но могут придать форме визуальную выразительность.
Затем откройте app.module.ts в редакторе кода и добавьте FormModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { PhoneNumberValidatorDirective } from './phone-number-validator.directive';
import { TemplateDrivenFormExampleComponent } from './template-driven-form-example.component';
@NgModule({
declarations: [
AppComponent
PhoneNumberValidatorDirective,
TemplateDrivenFormExampleComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
А теперь откройте app.component.html и замените его контент своим TemplateDrivenFormExample:
<app-template-driven-form-example></app-template-driven-form-example>
Вы можете запустить команду npm start и попробовать ввести данные в веб-браузере. Если вы введете меньше или больше 10 символов в поле для телефона, на экране отобразится сообщение об ошибке.
На этом этапе в вашей шаблонной форме есть пользовательский валидатор, использующий директиву.
Валидаторы в реактивных формах
Вместо директив реактивные формы используют в качестве валидаторов функции.
Сначала откройте свой терминал и используйте пакет @angular/cli, который был установлен как зависимость разработки:
./node_modules/@angular/cli/bin/ng generate component reactive-form-example --flat
Эта команда создаст файлы reactive-form-example.component.ts и reactive-form-example.component.html, а также добавит ReactiveFormExampleComponent в app.module.ts.
Затем откройте reactive-form-example.component.ts в редакторе кода и добавьте FormBuilder и AbstractControl:
import { Component, OnInit } from "@angular/core";
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-reactive-form-example',
templateUrl: './reactive-form-example.component.html',
styleUrls: ['./reactive-form-example.component.css']
})
export class ReactiveFormExampleComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.myForm = this.fb.group({
phone: ['', [ValidatePhone]]
});
}
saveForm(form: FormGroup) {
console.log('Valid?', form.valid); // true or false
console.log('Phone Number', form.value.phone);
}
}
function ValidatePhone(control: AbstractControl): {[key: string]: any} | null {
if (control.value && control.value.length != 10) {
return { 'phoneNumberInvalid': true };
}
return null;
}
Этот код создает функцию ValidatePhone и добавляет ее в массив валидаторов FormControl.
Откройте reactive-form-example.component.html в редакторе кода и создайте следующую форму:
<form class="needs-validation" novalidate [formGroup]="myForm" (ngSubmit)="saveForm(myForm)" > <div class="row"> <div class="form-group col-sm-4"> <label> Phone <input type="text" class="form-control" formControlName="phone" [class.is-invalid]="(myForm.get('phone').touched || myForm.get('phone').dirty) && myForm.get('phone').invalid" > </label> <span class="invalid-feedback" *ngIf="(myForm.get('phone').touched || myForm.get('phone').dirty) && myForm.get('phone').invalid" > Phone number must be 10 digits </span> </div> </div> </form>
В отличие от шаблонной формы, реактивная форма поддерживает form и использует [formGroup], (ngSubmit), formControlName и get.
Затем откройте app.module.ts в редакторе кода и добавьте ReactiveFormsModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { PhoneNumberValidatorDirective } from './phone-number-validator.directive';
import { ReactiveFormExampleComponent } from './reactive-form-example.component';
import { TemplateDrivenFormExampleComponent } from './template-driven-form-example.component';
@NgModule({
declarations: [
AppComponent,
PhoneNumberValidatorDirective,
ReactiveFormExampleComponent,
TemplateDrivenFormExampleComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Наконец, откройте app.component.html и замените текущий контент своим ReactiveFormExample:
<app-reactive-form-example></app-reactive-form-example>
Вы можете запустить команду npm start и попробовать ввести данные в веб-браузере. Если вы введете меньше или больше 10 символов в поле для телефона, на экране отобразится сообщение об ошибке.
На этом этапе в вашей реактивной форме есть пользовательский валидатор, использующий функцию.
Заключение
В этой статье вы научились добавлять пользовательские валидаторы для разных видов форм в приложении Angular.
Пользовательские валидаторы гарантируют, что значения, которые вводят посетители вашего приложения, соответствуют вашим ожиданиям.
Для более глубокого понимания концепций из этого руководства рекомендуем почитать больше об AbstractControl.
Tags: Angular, AngularJS, Node.js