我有两个表单字段,如果填写第一个字段,则第二个字段是必填字段。如果我尝试使用自定义验证器在Angular2中执行此操作,则仅在初始化和特定字段更改时触发验证器。
案例: - 用户填写字段1 - 字段2应该是必需的,但直到用户实际更改字段2(触发自定义验证)。
private createForm():void {
this.testForm = this._formBuilder.group({
'field1': [],
'field2': ['', this.validateRequired()]
});
}
private validateRequired(){
console.log("something", this);
let component = this;
return (control: Control): { [s: string]: boolean } => {
return component.testModel.field1 && !control.value {"required":true} : null;
}
}
请参阅此plunkr:http://plnkr.co/edit/PEY2QIegkqo8BW1UkQS5?p=preview
修改
现在我订阅了field1的valueChange observable,当更改时,对field2执行手动检查,如:
this.testForm.controls['field1'].valueChanges.subscribe(
value => {
component.testForm.controls['field2].updateValueAndValidity();
}
)
但我觉得必须有更好的方法来做到这一点。
答案 0 :(得分:1)
你可以像这样使用全局验证器:
private createForm():void {
this.testForm = this._formBuilder.group({
'field1': [],
'field2': ['', this.validateRequired()]
}, {
validator: this.someGlobalValidator // <-----
});
}
someGlobalValidator(group: ControlGroup) { // <-----
var valid = false;
for (name in group.controls) {
var val = group.controls[name].value
(...)
}
if (valid) {
return null;
}
return {
someValidationError: true
};
}
答案 1 :(得分:0)
为了解决Arne的评论,我想稍微扩展Thierry的答案。为了在formgroup级别验证器中处理多个字段和可能的多个验证的验证,解决方案是从验证器返回一个函数,然后返回一个指示错误类型的对象。下面是一个字段匹配验证器的示例,为了说明这一点,我添加了一些额外的错误。请注意,它返回一个可能具有多个属性的对象,其中每个对象属性都是任何字符串,值为布尔值。
export function FieldMatchingValidator(field1: string, field2 :string) {
return (cg: FormGroup): { [s: string]: boolean } => {
let retVal = null;
let f1 = cg.controls[field1];
let f2 = cg.controls[field2];
retVal = f1.value === f2.value ? null : { fieldMismatch: true };
if(somecondition){
retVal['someerror'] = true;
}
if(someothercondition){
retVal['someothererror'] = true;
}
return retVal;
}
}
当此验证程序运行时,如果遇到错误条件,则表单的errors属性将填充返回的对象,其中一个或多个属性指示不同的错误。然后,您只需要在具有验证错误的控件上设置适当的角度属性设置。
<div *ngIf="myForm.hasError('fieldMismatch')">
Field Mismatch
</div>
<div *ngIf="myForm.hasError('someerror')">
Some Error
</div>
<div [class.Errors]="myForm.hasError('someothererror')">
Some Other Error
</div>