我有以下代码片段,用于以Angular模板驱动形式验证密码和再次密码字段。这样的想法是,如果两个字段不同,则会在两个字段上附加一个错误。如果它们相同,则不会从两者中删除任何错误。
validate(control: AbstractControl): ValidationErrors | null {
// The current value
let currentValue = control.value;
// Control.root exposes the parent element of the directory
let otherField : AbstractControl = control.root.get(this.compareTo);
if(currentValue && otherField && currentValue !== otherField.value) {
otherField.setErrors({"fieldsMismatch": true});
otherField.markAsTouched();
setTimeout(() => {
control.setErrors({"fieldsMismatch" : true});
control.markAsTouched()}
)
} else {
control.setErrors(null)
otherField.setErrors(null)
}
return null;
}
1)如果我从setTimeout中删除了设置当前元素(控制)错误的逻辑,它将停止工作。为什么?
2)如果我使用清除错误
control.setError({"fieldsMismatch": null});
otherField.setError({"fieldsMismatch": null});
该错误已同时消除。但是,对于当前字段(控件),错误键设置为null,这意味着.ng-invalid
已从输入标签中删除。对于otherField,将错误设置为空对象,这意味着输入仍被标记为无效。为什么?我可以将错误显式设置为null,但是如果我还有其他验证也可以将其删除。
两个对象的类型均为AbstractControl,所以我不知道是什么引起了差异。
答案 0 :(得分:0)
一种更好的方法是创建一个表单组级别,以比较在您访问该表单组时在该级别上的两个字段,并设置错误以自行形成表单
检查此验证器
export function checkMatchValidator(field1: string, field2: string) {
return function (frm) {
let field1Value = frm.get(field1).value;
let field2Value = frm.get(field2).value;
if (field1Value !== '' && field1Value !== field2Value) {
return { 'match': `value ${field1Value} is not equal to ${field2Value}` }
}
return null;
}
}
密码/ confirmPassword表单
form: FormGroup
constructor(formBuilder: FormBuilder) {
this.form = formBuilder.group({
password: ['', Validators.required],
confirmPassword: ['', Validators.required],
},
{
validator: checkMatchValidator('password', 'confirmPassword')
}
);
}
}
基于表单状态的样式无效输入
.login-form.ng-invalid.ng-touched input {
border:1px solid red;
background:rgba(255,0,0,0.2);
}
答案 1 :(得分:0)
在有角度的模板驱动形式中,您可以使用实现验证器的指令(如果不需要传递参数,则不必要),请参见the docs
在这种情况下,我们可以使用类似
@Directive({
selector: '[repeatControl]',
providers: [{ provide: NG_VALIDATORS, useExisting: RepeatNameDirective, multi: true }]
})
export class RepeatNameDirective implements Validator {
@Input('repeatControl') control: NgControl;
validate(control: AbstractControl): { [key: string]: any } | null {
let invalid: boolean = this.control.value && control.value &&
this.control.value != control.value;
if (this.control.invalid != invalid)
setTimeout(() => {
this.control.control.updateValueAndValidity({ emitEvent: false })
})
return invalid ? { error: "Must be equal" }
: null;
}
}
看到我们需要将要比较的控件传递给参数,以允许我们进行updateValueAndValidity(否则一个控件将是无效的,而另一个控件将是无效的,反之亦然),并且需要将该指令置于setTimeOut下>
我们的表格变成
<input id="password" name="password" class="form-control"
[repeatControl]="repeatPassword"
[(ngModel)]="data.password" #password="ngModel" >
<input id="repeatPassword" name="repeatPassword" class="form-control"
[repeatControl]="password"
[(ngModel)]="data.repeatPassword" #repeatPassword="ngModel" >
<div *ngIf="repeatPassword.errors || password.errors">
Password and repeat password must be equals
</div>
请确保输入为referenceVariable 请参阅stackblitz(并考虑Angular如何将ng-invalid类自动添加到两个输入中)