【问题标题】:Reactive Form custom validation not working onBlur, Angular 7反应式表单自定义验证不适用于Blur,Angular 7
【发布时间】:2019-05-20 14:39:28
【问题描述】:

我在验证 Angular 7 中的确认传递字段 onBlur 时遇到问题。在我的情况下,我构建了多个自定义验证器,这些验证器在控件被设置为“脏”后工作,以及遵循 Pascal Prechts 教程的指令仅在字段被触摸时工作 onBlur,但我想要一个纯反应式解决方案,Pascal 需要添加到 HTML。

问题示例:点击进入 firstName 字段,立即选项卡或点击退出 - 内置必需的验证器触发。 点击进入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 但是....即使是这种情况,我也不知道该怎么做。

【问题讨论】:

  • 你能创建一个简单的 stackblitz.com 演示来演示这个问题吗?
  • 我去看看我能做什么耶
  • 这是一个问题的堆栈闪电:stackblitz.com/edit/angular-crnns8 请注意,在这个问题上,验证在 minLength、maxLength 和电子邮件模糊之前触发......我不太担心这个,因为它在原始项目上运行良好。然而,同样的问题在这个项目中被复制了——对于原始的 confirmPass,验证不会发生 onBlur,非常感谢任何帮助

标签: angular typescript


【解决方案1】:

Angular 第一次在 FormControl 创建时运行验证器,然后每次 FormControl 中的值发生变化。当您只关注和模糊输入时,不会进行重新验证。

对于required 字段,它的工作方式如下:当您创建FormControlFormBuilder 时,它得到验证并且从一开始就存在错误。它只是不可见,因为尚未触摸输入。对于matchingInputsValidator,错误不存在,因为两个字段在开始时是相同的,所以当你触摸输入时,不会显示错误。

您需要做的是在password 更改时自行触发confirmPass 表单控件的验证。这样做的一个好地方是valueChanges 订阅password 表单控件。

this.password.valueChanges.subscribe(() => this.confirmPass.updateValueAndValidity());

Here 你会发现更新的 stackblitz 演示。

【讨论】:

  • 嗨,在这种情况下,如何验证日期字段是否有效。
猜你喜欢
  • 2019-03-08
  • 2020-01-13
  • 2021-07-10
  • 2021-11-01
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 2020-04-06
  • 2018-06-16
相关资源
最近更新 更多