我需要一个验证,检查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
字段而不再订阅(并再次......)?
问题是,当FormControl的值发生变化时,放置在ValidatorFn
上的FormControl
显然只会被检查。我们想要的是检查email
或emailConfirm
何时发生变化。为此,我们需要验证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>
这是一种检查两个电子邮件是否相同的方法在您的验证等级类中编写此代码
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
} );
我建议你看一下github上的ngx-validation。它是一个小型的开源库,您既可以直接使用它,也可以将其分叉,或者只是看看它们是如何在那里完成的:
谢谢你们的好榜样。我有理由在表单上而不是在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的参考,而不是field1
和field2
然后你必须将formcontrols添加到你的formgroup等。我认为发送密钥工作正常。