我需要验证,检查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)
电子邮件:mattijs@foo.nl
确认电子邮件:mattijs@food.nl
*现在确认电子邮件显示错误,它不等于“电子邮件”。正确的。
2)
*现在我更改email
字段以匹配confirm email
字段。
电子邮件:mattijs@food.nl
确认电子邮件:mattijs@food.nl
* confirm email
字段上的错误不会消失,因为它不知道任何更改。
我遇到的问题是,我尝试在等号字段上使用valueChanges
observable来重新验证control
字段,但是当我启用control.updateValueAndValidity()
时在每个按键上以指数方式订阅,浏览器将崩溃。 IT确实会通知email confirm
字段重新验证,因此它几乎可以正常工作......
有没有人知道如何只让它订阅一次并重新验证control
字段而不再订阅(并再次......)?
答案 0 :(得分: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
} );
答案 1 :(得分:2)
我建议您在github上查看ngx-validation。 它是一个小型的开源库,您既可以直接使用它,也可以将其分叉,或者只是看看它们是如何在那里完成的:
答案 2 :(得分:1)
问题是ValidatorFn
放置在FormControl
上显然只会在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>
答案 3 :(得分: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 )
} );
}
}
我猜测代替field1
和field2
你也可以传递2个formcontrols的引用,但是你必须将formcontrols添加到你的表单组等。
我认为发送密钥效果很好。