angular - 反应式表单自定义验证不适用于Blur,Angular 7
问题描述
我在 Angular 7 中验证我的确认传递字段 onBlur 时遇到问题。在我的情况下,我构建了多个自定义验证器,这些验证器在控件被设置为“脏”后工作,以及遵循 Pascal Prechts 教程的指令,它在当字段只被触及,但我想要一个纯反应式解决方案,Pascal 需要添加到 HTML。
问题示例:点击进入名字字段,立即选项卡或点击退出 - 内置所需的验证器触发。点击进入confirmPass字段,立即点击或跳出;自定义验证器不会触发(甚至控制台日志也没有显示)。如果您要在制表符或单击之前键入任何单个字符,那么我制作的每个版本都可以正常工作。
我尝试使用多个静态方法构建一个验证器类。控制所有使用的一种方法('director'),该方法检查传入的字段名并适当地重定向。这直接返回了错误映射或空值而不是函数,当然没有用。
接下来我尝试了 Pascal Prechts 教程;https://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html用作指令 - 但是我必须在 HTML 中输入 equalValidator - 我没有想做。
最后我尝试了 Angular 建议的函数和我在 StackOverflow 上找到的另一个函数,它们都返回一个函数;它本身返回错误映射或 null。
表单组
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 };
}
我希望我的函数在字段被触摸和/或脏时运行,但它目前仅在字段脏时运行。在一个理想的世界中,我希望能够使用我自己的自定义函数扩展 Validators 或 NG_VALIDATORS 类,这完全来自 FormBuilder 声明。在这一点上,我相信它与多提供者有关,并且扩展了 NG_VALIDATORS 但是....即使是这种情况,我也不知道该怎么做。
解决方案
Angular 在创建时第一次运行验证器FormControl
,然后每次在该FormControl
. 当您只关注和模糊输入时,不会进行重新验证。
对于required
字段,它的工作方式如下:当您创建FormControl
低谷时FormBuilder
,它会得到验证,并且从一开始就存在错误。它只是不可见,因为尚未触摸输入。因为matchingInputsValidator
错误不存在,因为两个字段在开始时是相同的,所以当您触摸输入时,不会显示错误。
您需要做的是在confirmPass
表单控件password
发生更改时自行触发验证。这样做的一个好地方是valueChanges
订阅password
表单控件。
this.password.valueChanges.subscribe(() => this.confirmPass.updateValueAndValidity());
在这里,您将找到更新的 stackblitz 演示。
推荐阅读
- laravel - Laravel:ErrorException 未定义的变量:项目
- r - 在 R 中过滤数据的更有效方法
- regex - 正则表达式 - 引号和括号之间的文本
- firebase - 使用 gsutil 创建存储桶时出错
- firebase - Firebase:函数触发器:以前可以工作的函数,现在失败并显示“CANCELLED:操作已取消”。
- html - 仅在 chrome 中扭曲的 RTL 文本
- android - Android应用程序,有没有办法让另一台设备访问该网址而无需用户手动输入?
- node.js - 我是 API 新手。我正在使用 node js 中的 rest API。我不知道如何从一条路线转到另一条路线?
- java - 如何解决线程“main”中的异常 java.lang.NoSuchFieldError: INSTANCE
- python - 我如何制作一个 cron.yaml 文件来为谷歌云应用引擎每小时运行一次 python 脚本