Вот как мне удалось реализовать валидацию по группам ( Пример Stackblitz ).
(для фрагментов, которые я вставил ниже, многоточие в скобкахуказать, что части были опущены для ясности; обратитесь к приведенному выше примеру 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">
И вуаля, группа в целом была подтверждена моими специальными функциями.