angular4:使用valueChanges observable进行自定义'等于'验证

问题描述 投票:1回答:4

我需要一个验证,检查email是否等于Email Confirm。为此,我创建了一个看起来像的自定义验证

import { AbstractControl, ValidationErrors, FormGroup } from '@angular/forms';

export function ValidateEqual( equals: string ) {
  return ( control: AbstractControl ): ValidationErrors | null => {

    const equalsField = control.root.get( equals )
    if ( equalsField ) {

      equalsField.valueChanges.subscribe( value => {
        console.log( 'observable fired', value );
        // control.updateValueAndValidity( { onlySelf: true  , emitEvent: false } );
      } );
      if ( control.value !== equalsField.value ) {
        return { equals: true };
      }
    }
    return null;
  }
}

我的表格看起来像

this.loginForm = this.fb.group( {
  password: [ '', [
    Validators.required,
  ] ],
  email: [ '', [
    Validators.required,
    Validators.email,
  ] ],
  emailConfirm: [ '', [
    Validators.required,
    Validators.email,
    ValidateEqual( 'email' ),
  ] ]
} );

所以我在ValidateEqual()中通过该字段来检查相等性作为参数。这很好。

以下方案失败:

1)

电子邮件:[email protected]

确认电子邮件:[email protected]

*现在确认电子邮件显示错误,它不等于“电子邮件”。正确。

2)

*现在我改变email字段以匹配confirm email字段。

电子邮件:[email protected]

确认电子邮件:[email protected]

* confirm email字段上的错误不会消失,因为它不知道任何更改。

我的问题是,我试图在equals字段上使用valueChanges observable让control字段重新验证,但是当我启用control.updateValueAndValidity()时,它会在每个按键上以指数方式订阅,浏览器将崩溃。 IT确实通知email confirm字段重新验证,所以它几乎可以工作......差不多。

有没有人知道如何只让它订阅一次并让它重新验证control字段而不再订阅(并再次......)?

angular validation observable
4个回答
1
投票

问题是,当FormControl的值发生变化时,放置在ValidatorFn上的FormControl显然只会被检查。我们想要的是检查emailemailConfirm何时发生变化。为此,我们需要验证FormGroup而不仅仅是FormControl。因为ValidatorFn收到AbstractControl,这意味着我们的函数可以接收FormGroup,FormControl或FormArray。

static matches(form: AbstractControl){
    return form.get('email').value == form.get('emailConfirm').value ? null : {equals: true};
}

现在,在您的组件中,您仍然需要添加此验证器,它有点不同:

this.form = this.fb.group({...}, {validator: CustomValidator.matches});

正如您所看到的,我们可以将第二个对象作为参数传递给整个FormGroup的验证器

在模板中,您将检查整个表单是否具有等于错误而不是单个FormControl:

<div *ngIf="form.hasError('equals')">The emails don't match</div>

3
投票

这是一种检查两个电子邮件是否相同的方法在您的验证等级类中编写此代码

export class emailValidation {
    static matchEmail(AC: AbstractControl){
        let email=AC.get('email').value;
        let emailConfirm=AC.get('emailConfirm').value;
        if(email!=emailConfirm){
            console.log(false);
        }
    }
}

并在您的组件中添加此代码

this.loginForm = this.fb.group( {
  password: [ '', [
    Validators.required,
  ] ],
  email: [ '', [
    Validators.required,
    Validators.email,
  ] ],
  emailConfirm: [ '', [
    Validators.required,
    Validators.email,
  ] ]
},
{
    validator:passwordValidation.matchPassword
    } );

2
投票

我建议你看一下github上的ngx-validation。它是一个小型的开源库,您既可以直接使用它,也可以将其分叉,或者只是看看它们是如何在那里完成的:


0
投票

谢谢你们的好榜样。我有理由在表单上而不是在formControl上执行此操作,因为它不知道如何对其他控件做出反应/响应。

我稍作调整,以便控制在Equal验证器中比较的字段。我还在field2控件上设置了错误,这样我就不必在我的字段下面的某处添加单独的错误消息(我使用Material design mat-form-fields):

interface IEmailMatchFields {
  field1: string;
  field2: string;
}
export class EmailMatch {

  fields: IEmailMatchFields;
  constructor( fields: IEmailMatchFields ) {
    this.fields = fields;
  }
  emailMatches( form: AbstractControl ) {

    if ( this.fields ) {
      if ( form.get( this.fields.field1 ).value == form.get( this.fields.field2 ).value ) {
        form.get( this.fields.field2 ).setErrors( { 'emailNotEq': false } );
        form.get( this.fields.field2 ).updateValueAndValidity( { onlySelf: true } );
        return null;
      } else {
        form.get( this.fields.field2 ).setErrors( { 'emailNotEq': true } );
        return { emailNotEq: true };
      }
    }
  }
}

export class MyComponent implements OnInit {
  emailMatch: EmailMatch;
  registerForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) {
    this.emailMatch = new EmailMatch( { field1: 'email', field2: 'emailConfirm' } );
  }

  ngOnInit(): void {
    this.registerForm = this.fb.group( {
      password: [ '', [
        Validators.required,
      ] ],
      email: [ '', [
        Validators.required,
        Validators.email,
      ] ],
      emailConfirm: [ '', [
        Validators.required,
        Validators.email,
      ] ]
    }, {
      validator: this.emailMatch.emailMatches.bind( this.emailMatch )
    } );
  }
}

我想你可以传递2个formcontrols的参考,而不是field1field2然后你必须将formcontrols添加到你的formgroup等。我认为发送密钥工作正常。

© www.soinside.com 2019 - 2024. All rights reserved.