响应式表单验证。这样的表单验证,不是通过在模板上增加属性来添加验证,应该在组件类中直接把验证器函数添加到表单控件模型上。然后 ,一旦控件发生了变化,这些变化就会反应在相应的模板上。
内置验证器函数,就是使用angular forms的validators来实现的
test = new FormControl(this.test,
[
Validators.required,
...
])
如果不想使用angular 自带的验证器函数,就可以选择自定义的验证器。这样的自定义验证器函数的实现方式也可以是函数形式或者是指令的形式。
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const forbidden = nameRe.test(control.value);
return forbidden ? {
forbiddenName: {
value: control.value
}
} : null;
}
}
profileForm = new FormGroup({
gentle: new FormControl(''),
age: new FormControl(123, [forbiddenNameValidator(/0/i)])
})
如果想要使用模板驱动表单验证,那就需要通过生成这样的directive.ts.定义指令使用。这种方式生成的验证指令是同时适用于模板驱动表单验证和相应式表单验证,可以说比函数形式更加通用。举个例子:
import { Directive, Input } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator } from '@angular/forms';
import { forbiddenNameValidator } from './forbidden-name.directive';
@Directive({
selector: '[appForbiddenName]',
providers: [{
provide: NG_VALIDATORS, useExisting: ForbiddenNameValidatorDirective, multi: true
}]
})
export class ForbiddenNameValidatorDirective implements Validator {
@Input('appForbiddenName') forbiddenName = "";
validate(control: AbstractControl<any, any>): ValidationErrors | null {
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control) : null;
}
registerOnValidatorChange?(fn: () => void): void {
throw new Error('Method not implemented.');
}
}
<input
type="text"
class="form-control"
required
minlength="4"
appForbiddenName="0"
[(ngModel)]="names"
#nameModel="ngModel"
class="form-control"
/>