我在验证我在Angular 7中onBlur上的Confirm-pass字段时遇到问题。就我而言,我构建了多个自定义验证器,这些控件在控件被设置为“脏”后可以正常工作,以及在Pascal Prechts教程之后的指令仅在触摸字段时可以在onBlur上工作,但是我想要一个纯粹的Reactive解决方案,而Pascal要求将其添加到HTML。
问题示例:单击进入firstName字段,立即选项卡或单击out-内置必需的验证器将触发。 点击进入confirmPass字段,立即点击或跳出;自定义验证程序不会触发(即使控制台日志也未显示)。如果您要在制表符或单击之前键入任何单个字符,那么我制作的每个版本都可以使用。
我尝试用多个静态方法构建一个验证器类。控制所有使用的一种方法(“导演”),该方法检查传入的字段名并进行适当的重定向。这直接返回错误映射或空值而不是函数,并且当然不起作用。
接下来,我尝试了Pascal Prechts教程; https://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html用作指令-我不得不在HTML中输入equalValidator-我不想这样做。
最后,我尝试了Angular建议的函数,以及在StackOverflow上找到的另一个函数,它们都返回一个函数;它本身返回错误图或null。
FormGroup
ngOnInit() {
this.regForm = this.fb.group({
firstName: ["", [Validators.required, Validators.minLength(2), Validators.maxLength(30)]],
lastName: ["", [Validators.required, Validators.minLength(2), Validators.maxLength(30)]],
email: ["", [Validators.required, Validators.email]],
password: ["", [Validators.required, Validators.minLength(8), Validators.maxLength(55)]],
confirmPass: ["", matchingInputsValidator],
}, { updateOn: 'blur' });
this.lgnForm = this.fb.group({
lgnEmail: ["", [Validators.required, Validators.email]],
lgnPass: ["", Validators.required]
}, { updateOn: 'blur' });
}
适用于Blur的Pascals解决方案,但仅作为指令
function validateEqualFactory(compare: string) : ValidatorFn {
return (c: FormControl) => {
// value of confirm password field
let v = c.value;
// value of compared field - in this case 'password'
let e = c.root.get(compare);
// Ternary operator -> return null if equal or error map if not equal/password does not exist
return (e && v === e.value) ? null : { misMatch: true };
};
}
@Directive({
selector: '[validateEqual][formControl],[validateEqual][formControlName]',
providers: [
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true }
]
})
export class EqualValidator implements Validator {
validator: ValidatorFn;
constructor() {
this.validator = validateEqualFactory("password");
}
validate(c: FormControl) {
return this.validator(c);
}
}
最后我做了两次最近的尝试,第一个是Angular文档官方推荐的变体
export function confirmPassVal(): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
console.log("Making it here 1", control);
const passCtrl = control.root.get('password');
console.log("Making it here 2: ", passCtrl);
return (passCtrl && passCtrl.value === control.value) ? null : {"misMatch" : true };
}
}
export const matchingInputsValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
let pass;
control.root.get('password') ? pass = control.root.get('password').value : pass = null;
let confirmPass = control.value;
return pass === confirmPass ? null : { misMatch: true };
}
我希望我的函数在触摸和/或弄脏时可以运行,但是当前仅在弄脏时才运行。在理想的世界中,我希望能够纯粹通过FormBuilder声明使用我自己的自定义函数来扩展Validators或NG_VALIDATORS类。在这一点上,我认为它与多供应商和扩展NG_VALIDATORS有关,但是..即使是这种情况,我也不知道该怎么做。
答案 0 :(得分:1)
在创建FormControl
时,Angular会首先运行验证器,然后每次在FormControl
中更改值。当您只聚焦和模糊输入时,就不会进行任何重新验证。
对于required
字段,其工作方式如下:创建FormControl
槽FormBuilder
时,它会得到验证,并且错误从一开始就存在。它只是不可见,因为尚未触摸输入。对于matchingInputsValidator
,错误不存在,因为两个字段的开头都相同,因此当您触摸输入时,不会显示任何错误。
您需要做的是,只要confirmPass
发生更改,就可以自己触发password
表单控件的验证。做到这一点的一个好地方是valueChanges
表单控件的password
订阅。
this.password.valueChanges.subscribe(() => this.confirmPass.updateValueAndValidity());
Here,您将找到更新的stackblitz演示。