背景
仅当该组及其所有子级的所有同步验证均有效时,才对FormGroup执行异步验证。
问题
我想在所有子项均有效之前在FormGroup上执行asyncValidator。
this.myForm = new FormGroup({
country: [ null, [ Validators.required ] ],
postalCode: [ null ],
unrelatedField1: [ null ],
unrelatedField2: [ Validators.min(123) ]
}, {
validators: [ postalCodeFormat ],
asyncValidators: [ postalCodeExists ]
})
我的自定义postalCodeExists验证器需要使用country和postalCode字段。它不在乎'unrelatedField2'的有效性。
有什么方法可以手动触发FormGroup的异步验证吗?
我的第一个想法
据我所知这是不可能的。
this.myForm.valueChanges.pipe(
map(...etc),
distinctUntilChanges(...etc)
).subscribe(() => {
if (this.myForm.get('country').valid && this.myForm.get('postalCode').valid) {
this.myForm.executeAsyncValidationPlease();
}
});
我的第二个主意
this.myForm = new FormGroup({
countryAndPostalCodeGroup: new FormGroup({
country: [ null, [ Validators.required ] ],
postalCode: [ null ],
}, {
validators: [ postalCodeFormat ],
asyncValidators: [ postalCodeExists ]
}),
unrelatedField1: [ null ],
unrelatedField2: [ Validators.min(123) ]
})
它将起作用。但是我不喜欢。我强烈希望为myForm,所有API和数据存储使用一种数据结构。进行this.myForm.setValue(dataFromApi)
或相反的.getValue()
变体真的很有帮助。
答案 0 :(得分:1)
另一种方法是将异步验证器添加到每个FormControl中,并引用控件的父级以获得所需的其他值。本示例比较两个字符串(登录名/密码)以确保它们不匹配,即使extraField
无效也可以执行。
matching-validator.ts(该计时器用于模拟)
import { FormControl, FormGroup } from '@angular/forms';
import { timer } from 'rxjs';
import { map } from 'rxjs/operators';
export const isMatchingValidator = (key: string) => {
return (control: FormControl) => {
return timer(500).pipe(
map(() => {
const group = control.parent as FormGroup;
const key1 = group.get(key).value;
const key2 = control.value;
return key1 === key2 ?
{ matching: true } :
null;
})
);
};
}
表单创建:
this.form = new FormGroup({
login: new FormControl(
null,
Validators.required,
isMatchingValidator('password')
),
password: new FormControl(
null,
Validators.required,
isMatchingValidator('login')
),
extraField: new FormControl(
null, Validators.required
)
});
如果您在任何字段中都存在错误,则可以在标记中显示该错误:
<div *ngIf="form.get('login').hasError('matching') || form.get('password').hasError('matching')">
ID and Password can't match.
</div>
这是我从我派生的异步验证器示例中编辑的堆栈闪电: https://stackblitz.com/github/casetolleson/custom-async-validator