In this post I’ll be sharing how to build a custom from validator for Angular apps and add this validator to Template-Driven Forms or Reactive Forms.
在本文中,我将分享如何从Angular应用的验证器构建自定义并将此验证器添加到Template-Driven Forms或Reactive Forms中 。
Here, I’m going to demonstrate the validation of a phone number input field, which should be of 10 digits.
在这里,我将演示电话号码输入字段的验证,该字段应为10位数字。
Here are two screenshots that illustrate what our validation will look-like UI-wise:
以下是两个屏幕截图,它们说明了我们的验证在UI方面的外观:
模板驱动表单的验证器 (Validator for Template-Driven Form)
For validation in template-driven forms, directives are used, so let’s go ahead and create a phone-number-validator
directive.
为了以模板驱动形式进行验证,使用了伪指令,因此让我们继续创建一个phone-number-validator
伪指令。
import { Directive } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[phoneValidateDirective]',
providers: [{
provide: NG_VALIDATORS,
useExisting: AppPhoneValidateDirective,
multi: true
}]
})
export class AppPhoneValidateDirective implements Validator {
validate(control: AbstractControl) : {[key: string]: any} | null {
if (control.value && control.value.length != 10) {
return { 'phoneNumberInvalid': true }; // return object if the validation is not passed.
}
return null; // return null if validation is passed.
}
}
Don’t forget to register and add the validator to the existing validator array NG_VALIDATORS
provided by Angular:
不要忘记注册验证器并将其添加到NG_VALIDATORS
提供的现有验证器数组NG_VALIDATORS
:
// ...
providers: [{
provide: NG_VALIDATORS,
useExisting: Your_Class_Name,
multi: true
}]
// ...
Here I’ve created the phone directive which implements Validator
of @angular/forms
, for which we have to provide the following implementation method: validate(control: AbstractControl): : {[key: string]: any} | null
. This validator will return an object if the validation is not passed which is { 'phoneNumberInvalid': true }
and will return null if the validation is passed.
在这里,我创建了实现@angular/forms
Validator
的phone指令,为此,我们必须提供以下实现方法: validate(control: AbstractControl): : {[key: string]: any} | null
validate(control: AbstractControl): : {[key: string]: any} | null
。 如果未通过验证( { 'phoneNumberInvalid': true }
,则此验证器将返回一个对象;如果通过验证,则该验证器将返回null。
Angular adds the return value of the validation function in the errors
property of FormControl / NgModel. If the errors
property of the FormControl / NgModel is not empty then the form is invalid and if the errors property is empty then the form is valid.
Angular在FormControl / NgModel的errors
属性中添加了验证函数的返回值。 如果FormControl / NgModel的errors
属性不为空,则该表单无效;如果errors属性为空,则该表单有效。
<div class="form-group col-sm-4">
<label for="">Phone</label>
<input type="text" class="form-control" name="phone" [(ngModel)]="phone" [class.is-invalid]="phonengModel.errors?.phoneNumberInvalid && (phonengModel.touched || phonengModel.dirty)" #phonengModel="ngModel" phoneValidateDirective> <!-- Added directive to validate phone -->
<span class="invalid-feedback" *ngIf="(phonengModel.touched || phonengModel.dirty) && phonengModel.errors?.phoneNumberInvalid"> <!-- Checked the errors property contains the 'phoneNumberInvalid' property or not which is returned by the validation function -->
Phone number must be of 10 digit
</span>
</div>
验证表单验证器 (Validator for Reactive Forms)
For validation in Reactive Forms we have to create a function.
为了在Reactive Forms中进行验证,我们必须创建一个函数。
import { FormBuilder, AbstractControl } from '@angular/forms';
import { Component, OnInit } from "@angular/core";
@Component({
selector: 'reactive-form',
templateUrl: './reactive-form.component.html'
})
export class AppReactiveForm implements OnInit {
myForm: FormGroup;
constructor(
private fb: FormBuilder
) {}
ngOnInit() {
this.myForm = this.fb.group({
phone: ['', [ValidatePhone]] // added the function in validators array of form-control
});
}
}
function ValidatePhone(control: AbstractControl): {[key: string]: any} | null {
if (control.value && control.value.length != 10) {
return { 'phoneNumberInvalid': true };
}
return null;
}
We are adding the function to the validators array of FormControl.
我们将函数添加到FormControl的验证器数组中。
<form [formGroup]="myForm" novalidate class="needs-validation" (ngSubmit)="saveForm(myForm)">
<div class="row">
<div class="form-group col-sm-4">
<label for="">Password</label>
<input type="text" class="form-control " formControlName="phone" [class.is-invalid]="(myForm.get('phone').touched || myForm.get('phone').dirty) && myForm.get('password').">
<span class="invalid-feedback" *ngIf="(myForm.get('password').touched || myForm.get('password').dirty) && myForm.get('password').invalid">
Password is required
</span>
</div>
</div>
</form>
结合两个验证器 (Combining Both Validators)
We can combine both validators so that we do not repeat our code and follow DRY (Don’t Repeat Yourself) principles:
我们可以结合使用两个验证器,以免重复代码并遵循DRY (请勿重复自己)原则:
import { Directive } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
export function ValidatePhone(control: AbstractControl): {[key: string]: any} | null {
if (control.value && control.value.length != 10) {
return { 'phoneNumberInvalid': true };
}
return null;
}
@Directive({
selector: '[phone]',
providers: [{
provide: NG_VALIDATORS,
useExisting: AppPhoneValidateDirective,
multi: true
}]
})
export class AppPhoneValidateDirective implements Validator {
validate(control: AbstractControl) : {[key: string]: any} | null {
return ValidatePhone(control);
}
}
That’s it for now! For a deeper understanding of the concepts from this post, visit this post on Providers and read about AbstractControl
现在就这样! 要更深入地了解本文中的概念,请访问Providers上的该文章并阅读有关AbstractControl的信息。
翻译自: https://www.digitalocean.com/community/tutorials/angular-custom-validation