这就是我成功实现分组验证的方式(堆栈闪电战示例 https://stackblitz.com/edit/angular-v9rjzw).
(对于我在下面粘贴的片段,括号中的省略号表示为了清晰起见,省略了这些部分;有关完整内容,请参阅上面的 stackblitz 示例)
对于每个组,我添加了一个包装元素(我认为它也可以是<ng-container>
,虽然没有测试它)只是为了承受ngModelGroup
指示:
<div ngModelGroup="contacts" (...) >
<h3>--- Contacts ---</h3>
email: (...input...)
phone: (...input...)
<div ngModelGroup="address" (...) >
<h4>---- Address ----</h4>
street: (...input...)
city: (...input...)
zipcode: (...input...)
</div>
</div>
现在这些新的每一个ngModelGroup
可以附加验证器。由于这些验证是如此临时,我觉得它们不值得真正可重用的实现,我所需要的只是验证函数(此处仅粘贴其中一个;另一个非常简单,您可以随时参考 stackblitz ):
ifOneThenFullAddress(c: AbstractControl): ValidationErrors | null {
let value = c.value;
let street = value && value.street;
let city = value && value.city;
let zipcode = value && value.zipcode;
if ((street && city && zipcode) || (!street && !city && !zipcode))
return null;
return { ifOneThenAll: '' };
}
(这段代码是在内部实现的UserDataComponent
)
现在要使角度形式引擎调用我的函数,我必须实现一个Validator
,但是一个通用的(将验证交给一个函数):
@Directive({
selector: '[fn-validate]',
providers: [{provide: NG_VALIDATORS, useExisting: FnValidateDirective, multi: true}]
})
export class FnValidateDirective implements Validator {
@Input('fn-validate') fn: (c: AbstractControl) => ValidationErrors | null;
validate(c: AbstractControl): ValidationErrors | null {
return this.fn(c);
}
}
要使用它(并绑定我的验证函数),我必须将组的元素更改为:
<div ngModelGroup="contacts" [fn-validate]="atLeastOneContact">
<div ngModelGroup="address" [fn-validate]="ifOneThenFullAddress">
瞧,整个团队得到了我的临时职能的验证。