EDIT: I've taken a different approach to solve this issue: retrieve dynamic child component values in the parent on save()
, as per accepted answer.
I'm trying to have a parent component emit an event/observable so its children dynamic components trigger an action upon listening to such.
I've learnt around that is not possible to use @Input()
nor @Output()
decorators with dynamic components, so...
This is an outline of my use case:
- Dynamic child component consists of a group of 4 input elements. (done)
- Parent component has
Add
button that adds dynamic child component. This button can be used to add as many instances of the dynamic child component. (done) - Dynamic child component has
Delete
button to remove its instance. (done) - Parent component has property of type Array of objects. Each array item is an object containing the dynamic component input values. (to do)
- Parent component has
Save
button, which on click should emit the event to the dynamic component instances, so each can save its input values as an object. (i.e. 3 instances =>[ {a:..., b:..., c:..., d:...}, {...}, {...} ]
; 5 instances => 5 array items and so on). (to do)
I'm trying to emit the parent event from Save button (#5 above), and have each existing instance of the dynamic child component to listen to the event and then do a .push
action on the parent array (#4 above).
Probably this is not best practice, but have not yet devised any other way to ensure that values are saved for the existing dynamic component instances after a potentially indeterminate, random number of add / remove instance actions have taken place.
Parent Component:
html
...
<button (click)="addDetailRow()" type="button">Add Detail Row</button>
<div #detailContainer></div>
...
<button (click)="save()">Save</button>
...
typescript
...
detailRowArray: Array<Object>;
...
addDetailRow() {
let comp = this._cfr.resolveComponentFactory(DetailRowComponent);
let detailRowComp = this.container.createComponent(comp);
detailRowComp.instance._ref = detailRowComp;
detailRowComp.instance.detailRowArray = this.detailRowArray;
}
save() {
// TODO: here emit an event/observable
}
...
Dynamic Child Component:
html
<div><input type="text" name="a" [(ngModel)]="detail_item.a" #a></div>
<div><input type="text" name="b" [(ngModel)]="detail_item.b" #b></div>
<div><input type="text" name="c" [(ngModel)]="detail_item.c" #c></div>
<div>
<input type="text" name="d" [(ngModel)]="detail_item.d" #d>
<span>
<button (click)="removeRow()">Remove Row</button>
</span>
</div>
typescript
...
detail_item: { [key: string]: any; } = {};
detailRowArray: Array<Object>;
...
removeRow() {
...
}
...
// TODO: trigger this function when parent emits event/observable
saveToParentArray() {
this.detailRowArray.push(this.detail_item);
}
P.S. Code base is using template driven form, so it is not possible to use the FormArray or so in it, (I'm just getting acquainted with angular 2+). Thanks for your attention.
EventEmitter
s) to broadcast changes to the parent. The parent should know about the children but not vice-versa. - Daniel W StrimpelInput()
orOutput()
to a dynamic component? - j4v1