Пользовательские валидаторы форм в 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