angular11源码探索十四[表单校验器]
自带的限制条件
Validators.required
报错
{'required': true}
验证字段值是否为true
Validators.requiredTrue
{required: true}
邮箱
Validators.email
{email: true}
最小长度
Validators.minLength(3)
{minlength: {requiredLength: 3, actualLength: 2}}
还可以直接在input使用
<input minlength="5">
最大长度
Validators.maxLength(5)
{maxlength: {requiredLength: 5, actualLength: 7}
<input maxlength="5">
正则
Validators.pattern(/foo/)
{pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}
<input pattern="[a-zA-Z ]*"> 这个页也可以直接在页面使用
自定过滤器
//这个传参数的版本
export function maxLength(maxLength: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors|null => {
return hasValidLength(control.value) && control.value.length > maxLength ?
{'maxlength': {'requiredLength': maxLength, 'actualLength': control.value.length}} :
null;
};
}
如果不传参数的话就是这样的
这个自己编写的自定义的
export type ValidationErrors = {
[key: string]: any
};
export function (control: AbstractControl): ValidationErrors|null {
return control.value.length > maxLength ?
{'maxlength': {'requiredLength': maxLength, 'actualLength': control.value.length}} :null;
};
}
这里可以参考源码中的写法
export interface Validator {
/**
这个是直接的
*/
validate(control: AbstractControl): ValidationErrors|null;
/**
注册一个回调函数,当验证器输入改变时调用, 暂时没发现用处
*/
registerOnValidatorChange?(fn: () => void): void;
}
管道的自定义指令的时候
@Directive({
selector: '[customValidator]',
// 注册指令,然后页面使用
providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
})
class CustomValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors|null {
return {'custom': true};
}
}
禁用清空错误
const arr = new FormArray([new FormControl()], () => ({'expected': true}));
arr.errors // {'expected': true}
arr.disable();
arr.errors // null
arr.enable(); //解除禁用,就继续报错
但是当禁用的时候,重新给数组添加一个FormControl
也促发脏依赖更新,所以也会报错
FomrBuilder
fbForm: FormGroup;
constructor(
private fb: FormBuilder
) {
this.fbForm = this.fb.group({
firstName: 'some value',
login: ['some',[Validators.required]],
//禁用
should: {value: 'should', disabled: true},
login:fb.control('',{updateOn:'blur'}),
});
this.fbForm = this.fb.group({
firstName: 'some value',
//第三个参数是异步校验器
login: ['some', null,[this.asyncValidator1, this.asyncValidator2]],
arrOne: this.fb.array(
['one', 'two'],
null,
[this.asyncValidator1, this.asyncValidator2]
)
}
);
console.log(this.fbForm.get('arrOne')?.errors);
console.log(this.fbForm.get('login')?.errors);
// {'async1': true, 'async2': true}
FormControl 第二个参数配置的几种形式
如果第一个参数,那么值主要看value的值,第二个参数还是校验
const control = new FormControl({ value: 'n/a', disabled: true });
const control = new FormControl('', Validators.required);
const control = new FormControl('', {
validators: Validators.required,// 校验器
asyncValidators: myAsyncValidator,// 异步校验器
updateOn: 'blur'// 校验方式
});
事件更新
更新策略AbstractControl(表示控件自行更新的事件)。
离开的时候,才会触发校验
可能的值:'change'| 'blur'| 'submit' 默认值:'change'
我们发现FormGroup, FormControl,FormArray 类似,第二个参数都可以这样写
this.fbForm = this.fb.group({
firstName: '',
},{updateOn: 'blur',validators:this.addFn}
);
const a = new FormArray([new FormControl(), new FormControl()], {updateOn: 'blur'});
const control = new FormControl('', { updateOn: 'blur' });
const control = new FormControl('', { updateOn: 'submit' });
====
addFn(control: AbstractControl) {
// 更改了,触发事件是失去焦点促发
if (control.dirty) {
console.log(control.value);
return {name1: true};
}
}
this.fbForm = this.fb.group({
firstName: ['some value', {
updateOn: 'blur',
validators: [this.addFn]
}],
three:fb.array([
'one','two'
])
})
console.log(this.fbForm.get(['three',1])?.value);// get 还能这样查
设置校验
setValidators
const c = new FormControl(null);
//单个值
c.setValidators(Validators.required);
// 多个值
c.setValidators([Validators.minLength(5), Validators.required]);
// 清空校验器
c.clearValidators();
//设置异步校验器
c.setAsyncValidators(asyncValidator('expected'));
//多个异步校验器
c.setAsyncValidators([asyncValidator('expected')]);
异步校验器
export function asyncValidator(expected: string, timeouts = {}): AsyncValidatorFn {
return (control: AbstractControl) => {
const timeout = (timeouts as any)[control.value] ?? 0;
const result = control.value != expected ? {async: true} : null;
return createValidationPromise(result, timeout);
};
}
function createValidationPromise(
result: ValidationErrors|null, timeout: number): Promise<ValidationErrors|null> {
return new Promise(resolve => {
if (timeout == 0) {
resolve(result);
} else {
setTimeout(() => {
resolve(result);
}, timeout);
}
});
}
使用案例
function asyncFnOne(c:string): AsyncValidatorFn {
return (control: AbstractControl)=> {
console.log(control.value);
return of({name1:true})
}
}
function asyncFnTwo(c:string): AsyncValidatorFn {
return (control: AbstractControl)=> {
console.log(control.value);
return of({name2:true})
}
}
this.profileForm = new FormGroup({
firstName: new FormControl(1, null!, [asyncFnOne('xxx'),asyncFnTwo('bbb')])
});
this.profileForm.get('firstName').asyncValidator(new FormControl(11))
.subscribe(console.log);
// {name1: true, name2: true}
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬