Я смог использовать привязки FormGroup, но сохранил логику / структуру внутри каждого дочернего элемента.Я нашел это решение, чтобы дать мне лучший баланс для целей, которые я искал.
Отказ от ответственности: я не претендую на оригинальность этого решения, это результат многих дней исследований и тестирования многихрешения в Интернете.
Таким образом, родительский компонент привязывается к дочернему элементу с помощью FormGroup:
<div class="sibling" *ngFor="let sibling of getSiblings(); let i = index;">
<app-child [form]="sibling" (deleted)="deleteSibling(i)"></app-child>
</div>
Метод getSiblings () в родительском элементе является простым помощником:
getSiblings(): AbstractControl[] {
return (<FormArray>this.form.get('siblings')).controls;
}
Ключевое различие заключается в том, как создаются родственные группы FormGroup на родительском элементе:
addSibling() {
(<FormArray>this.form.controls.siblings).push(ChildComponent.toFormGroup());
}
addSibling () выше использует статический метод из дочернего компонента для создания пустой FormGroup:
static toFormGroup(model: any = {}) {
return new FormGroup({
id: new FormControl(model.id, Validators.required),
firstName: new FormControl(model.firstName, Validators.required),
lastName: new FormControl(model.lastName, Validators.required),
});
}
Как видно выше, можно создавать не только пустые группы форм.Метод loadModel родительского объекта может использовать преимущества каждой дочерней логики для создания полевых групп FormGroup.Здесь у нас есть только один дочерний тип, но их может быть много:
loadModel(model: any) {
this.form.patchValue(model);
const formArray = this.form.get('siblings') as FormArray;
while (formArray.length) {
formArray.removeAt(0);
}
model.siblings.forEach(s => formArray.push(ChildComponent.toFormGroup(s)));
}
Сортировка и фильтрация также не сложны.Здесь есть несколько стратегий, но в качестве простого тестового примера:
orderChildren() {
this.currentModel.siblings = this.currentModel.siblings.sort((a, b) => a.id - b.id);
this.loadModel(this.currentModel);
}
При таком подходе я могу использовать каскадные функции Reactive Forms, такие как действительный статус, нетронутые / грязные флаги, события изменения и т. Д., Сохраняя логику /структура каждого потомка в своем классе компонентов.Так же, как пример, каскадную валидность можно увидеть в действии (красные границы) окончательного решения.
В качестве основной проблемы привязки к FormGroup было то, что логику / структуру дочерних элементов нужно было перенести в родительский.При таком подходе этого избегают, и поэтому я более готов признать, что это не может считаться плохой практикой.
Полный пример можно увидеть на StackBlitz: