Angular 6 反应式表单验证不适用于自定义验证器
Angular 6 reactive form validation not working with custom validator
所以我创建了一个自定义验证器来验证 "New Password" 字段和 "Confirm Password" 字段是否匹配。在组件级别,它工作得很好。仅当两个输入不匹配时才会显示错误消息。
问题是,我在表单有效之前禁用了提交按钮,但是当我使用这个自定义验证器时,整个表单从未通过验证。填写for表单时,所有组件验证都通过,但表单验证没有。
我在这里错过了什么?
自定义验证器代码如下所示:
import {FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
export const matchingInputsValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
let pass = control.get('NewPassword').value;
let confirmPass = control.get('ConfirmPassword').value;
return pass === confirmPass ? { matchingInputs: true } : { matchingInputs: false };
};
我将自定义验证器导入到我的组件中,并在组件中声明我的表单控件,如下所示:
expiredPasswordForm: FormGroup;
oldPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
newPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
confirmPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
在我的 ngOnInit() 生命周期钩子中,我创建了我的表单组,如下所示:
this.expiredPasswordForm = this.fb.group({
'OldPassword': this.oldPassword,
'NewPassword': this.newPassword,
'ConfirmPassword': this.confirmPassword
}, { validator: matchingInputsValidator});
我的 HTML 表单如下所示:
<form [formGroup]="expiredPasswordForm" ngNoForm action="" method="post" class="form-horizontal">
<label for="oldPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label" translate>Old Password</label>
<input [formControl]="oldPassword" type="password" class="form-control" id="oldPassword"
placeholder="Old Password" name="OldPassword" [ngClass]="{'is-invalid':oldPassword.invalid && (oldPassword.dirty || oldPassword.touched)}">
<div *ngIf="oldPassword.invalid && (oldPassword.dirty || oldPassword.touched)" class="invalid-feedback">
<span *ngIf="oldPassword.errors.required">Old Password is required</span>
</div>
<label for="newPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate>New Password</label>
<input [formControl]="newPassword" type="password" class="form-control" id="newPassword"
placeholder="New Password" name="NewPassword" [ngClass]="{'is-invalid':newPassword.invalid && (newPassword.dirty || newPassword.touched)}">
<div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)" class="invalid-feedback">
<span *ngIf="newPassword.errors.required">A new password is required</span>
</div>
<label for="confirmPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate>Confirm Password</label>
<input [formControl]="confirmPassword" type="password" class="form-control" id="confirmPassword"
placeholder="Confirm Password" name="ConfirmPassword" [ngClass]="{'is-invalid':confirmPassword.invalid && (confirmPassword.dirty || confirmPassword.touched)}">
<div *ngIf="confirmPassword.invalid && (confirmPassword.dirty || confirmPassword.touched)" class="invalid-feedback">
<span *ngIf="confirmPassword.errors.required">You must confirm your new password!</span>
</div>
<div *ngIf="!expiredPasswordForm.errors?.matchingInputs">
<span class="form-error-message">Passwords do not match!</span>
</div>
<div class="text-center">
<button [disabled]="!expiredPasswordForm.valid" type="submit" class="btn btn-primary mt-4 mb-2">Update Password</button>
</div>
</form>
我希望这些信息足够了。为什么这在组件级别有效,但在表单级别无效?提前致谢!
问题出在您的自定义验证器上。
您可能已经弄清楚了,因为它是唯一设置在 FormGroup
级别而不是 FormControl
级别的验证器
验证器 return 的对象属于 ValidationErrors
类型,它是一个包含 keys/values 对的对象。对于每一对,键代表错误的名称,值代表关联的数据(例如要显示的详细信息)。
所以如果你想让你的验证器 return 没有错误,你必须 return 什么都不做:
import {FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
export const matchingInputsValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
let pass = control.get('NewPassword').value;
let confirmPass = control.get('ConfirmPassword').value;
return pass === confirmPass ? null : { matchingInputs: false };
}
所以我创建了一个自定义验证器来验证 "New Password" 字段和 "Confirm Password" 字段是否匹配。在组件级别,它工作得很好。仅当两个输入不匹配时才会显示错误消息。
问题是,我在表单有效之前禁用了提交按钮,但是当我使用这个自定义验证器时,整个表单从未通过验证。填写for表单时,所有组件验证都通过,但表单验证没有。
我在这里错过了什么?
自定义验证器代码如下所示:
import {FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
export const matchingInputsValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
let pass = control.get('NewPassword').value;
let confirmPass = control.get('ConfirmPassword').value;
return pass === confirmPass ? { matchingInputs: true } : { matchingInputs: false };
};
我将自定义验证器导入到我的组件中,并在组件中声明我的表单控件,如下所示:
expiredPasswordForm: FormGroup;
oldPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
newPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
confirmPassword = new FormControl('', Validators.compose([Validators.required, Validators.minLength(4)]));
在我的 ngOnInit() 生命周期钩子中,我创建了我的表单组,如下所示:
this.expiredPasswordForm = this.fb.group({
'OldPassword': this.oldPassword,
'NewPassword': this.newPassword,
'ConfirmPassword': this.confirmPassword
}, { validator: matchingInputsValidator});
我的 HTML 表单如下所示:
<form [formGroup]="expiredPasswordForm" ngNoForm action="" method="post" class="form-horizontal">
<label for="oldPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label" translate>Old Password</label>
<input [formControl]="oldPassword" type="password" class="form-control" id="oldPassword"
placeholder="Old Password" name="OldPassword" [ngClass]="{'is-invalid':oldPassword.invalid && (oldPassword.dirty || oldPassword.touched)}">
<div *ngIf="oldPassword.invalid && (oldPassword.dirty || oldPassword.touched)" class="invalid-feedback">
<span *ngIf="oldPassword.errors.required">Old Password is required</span>
</div>
<label for="newPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate>New Password</label>
<input [formControl]="newPassword" type="password" class="form-control" id="newPassword"
placeholder="New Password" name="NewPassword" [ngClass]="{'is-invalid':newPassword.invalid && (newPassword.dirty || newPassword.touched)}">
<div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)" class="invalid-feedback">
<span *ngIf="newPassword.errors.required">A new password is required</span>
</div>
<label for="confirmPassword" class="col-sm-4 col-md-6 col-lg-6 col-xl-6 control-label mt-2" translate>Confirm Password</label>
<input [formControl]="confirmPassword" type="password" class="form-control" id="confirmPassword"
placeholder="Confirm Password" name="ConfirmPassword" [ngClass]="{'is-invalid':confirmPassword.invalid && (confirmPassword.dirty || confirmPassword.touched)}">
<div *ngIf="confirmPassword.invalid && (confirmPassword.dirty || confirmPassword.touched)" class="invalid-feedback">
<span *ngIf="confirmPassword.errors.required">You must confirm your new password!</span>
</div>
<div *ngIf="!expiredPasswordForm.errors?.matchingInputs">
<span class="form-error-message">Passwords do not match!</span>
</div>
<div class="text-center">
<button [disabled]="!expiredPasswordForm.valid" type="submit" class="btn btn-primary mt-4 mb-2">Update Password</button>
</div>
</form>
我希望这些信息足够了。为什么这在组件级别有效,但在表单级别无效?提前致谢!
问题出在您的自定义验证器上。
您可能已经弄清楚了,因为它是唯一设置在 FormGroup
级别而不是 FormControl
验证器 return 的对象属于 ValidationErrors
类型,它是一个包含 keys/values 对的对象。对于每一对,键代表错误的名称,值代表关联的数据(例如要显示的详细信息)。
所以如果你想让你的验证器 return 没有错误,你必须 return 什么都不做:
import {FormGroup, ValidationErrors, ValidatorFn} from "@angular/forms";
export const matchingInputsValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
let pass = control.get('NewPassword').value;
let confirmPass = control.get('ConfirmPassword').value;
return pass === confirmPass ? null : { matchingInputs: false };
}