【发布时间】:2018-09-30 15:10:50
【问题描述】:
编辑:我采取了不同的方法来解决这个问题:根据接受的答案,在 save() 上的父级中检索动态子组件值。
我正在尝试让父组件发出一个事件/可观察的,以便其子动态组件在侦听此类事件时触发一个动作。
我了解到不能将 @Input() 或 @Output() 装饰器与动态组件一起使用,所以...
这是我的用例大纲:
- 动态子组件由一组 4 个输入元素组成。 (完成)
- 父组件具有添加动态子组件的
Add按钮。此按钮可用于添加尽可能多的动态子组件实例。 (完成) - 动态子组件有
Delete按钮来删除它的实例。 (完成) - 父组件具有对象数组类型的属性。每个数组项都是一个包含动态组件输入值的对象。 (做)
- 父组件具有
Save按钮,单击该按钮应将事件发送到动态组件实例,因此每个都可以将其输入值保存为对象。 (即 3 个实例 =>[ {a:..., b:..., c:..., d:...}, {...}, {...} ];5 个实例 => 5 个数组项等等)。 (做)
我正在尝试从“保存”按钮(上面的#5)发出父事件,并让动态子组件的每个现有实例侦听该事件,然后对父数组执行 .push 操作(# 4)。
这可能不是最佳实践,但尚未设计任何其他方式来确保在发生潜在不确定的随机数量的添加/删除实例操作后为现有动态组件实例保存值。
父组件:
html
...
<button (click)="addDetailRow()" type="button">Add Detail Row</button>
<div #detailContainer></div>
...
<button (click)="save()">Save</button>
...
打字稿
...
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
}
...
动态子组件:
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>
打字稿
...
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);
}
附:代码库使用模板驱动的表单,所以不能在其中使用 FormArray 左右,(我刚刚熟悉 angular 2+)。感谢您的关注。
【问题讨论】:
-
您可以在动态组件上拥有输入/输出,您只需自己连接它们。您的动态组件最好使用输出(
EventEmitters 的公共属性)将更改广播到父级。父母应该了解孩子,但反之则不然。 -
感谢@DanielWSrimpel。关于如何将
Input()或Output()连接到动态组件的任何提示?
标签: angular typescript eventemitter