我有一个“仪表板”,可以加载已配置的元素。 仪表板模板具有:
<div class="dash-container" [ngGrid]="gridConfig">
<div *ngFor="let box of boxes; let i = index"
[(ngGridItem)]="box.config"
(onItemChange)="updateItem(i, $event)"
(onResize)="onResize(i, $event)"
(onDrag)="onDrag(i, $event)"
(onDragStop)="onDragStop(i,$event)"
[ngClass]="box.class"
>
<div class="handle"><h4>{{box.title}}</h4></div>
<div [innerHTML]= "box.content"></div>
</div>
</div>
现在<div [innerHTML]= "box.content"></div>
将无效,因为非标准元素已被清理。
运行最新的Angular 2.4.6(RC 6)。
我看一下我能找到的动态组件的例子 - 但我看到的只是他们只是将组件添加到当前组件 - 但我需要它们在非常特定的div中,如上例所示。
ComponentFactoryResolver
通常与@ViewChild
一起使用。
但我不能在循环中这样做:
ngAfterViewInit() {
const dashWidgetsConf = this.widgetConfigs();
for (var i = 0; i < dashWidgetsConf.length; i++) {
const conf = dashWidgetsConf[i];
@ViewChild(conf.id, {read: ViewContainerRef}) var widgetTarget: ViewContainerRef;
var widgetComponent = this.componentFactoryResolver.resolveComponentFactory(UnitsComponent);
widgetTarget.createComponent(widgetComponent);
}
}
@viewchild给'装饰者在这里无效'。
如何从conf列表中加载组件(在循环中)并将它们添加到我的组件中的特定div(div得到#{{conf.id}}
)中?
答案 0 :(得分:19)
经过一番研究,这是我提出的解决方案(在角4.0.0中工作)。
按ID:
加载所有ViewContainerRef
目标
@ViewChildren('dynamic', {read: ViewContainerRef}) public widgetTargets: QueryList<ViewContainerRef>;
然后循环遍历它们以获取目标,为组件创建工厂并调用createComponent
也可以使用组件引用来订阅或设置其他组件属性。
ngAfterViewInit() {
const dashWidgetsConf = this.widgetConfigs();
const widgetComponents = this.widgetComponents();
for (let i = 0; i < this.widgetTargets.toArray().length; i++) {
let conf = dashWidgetsConf[i];
let component = widgetComponents[conf.id];
if(component) {
let target = this.widgetTargets.toArray()[i];
let widgetComponent = this.componentFactoryResolver.resolveComponentFactory(component);
let cmpRef: any = target.createComponent(widgetComponent);
if (cmpRef.instance.hasOwnProperty('title')) {
cmpRef.instance.title = conf.title;
}
}
}
}
widgetComponents
是一个对象{key: component}
,widgetConfigs
是我存储特定组件信息的地方 - 例如标题,组件ID等。
然后在模板中:
<div *ngFor="let box of boxes; let i = index" >
<ng-template #dynamic></ng-template>
</div>
目标的顺序与我的conf中相同(boxes
是从它生成的) - 这就是为什么我可以按顺序遍历它们并使用i作为索引来获取正确的conf和组件。
答案 1 :(得分:1)
在
if (cmpRef.instance.hasOwnProperty('title')) {
cmpRef.instance.title = conf.title;
}
您可以添加this.cd.detectChanges();
或者你的子组件中使用Angular 6x时会出现错误“ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化”。
答案 2 :(得分:0)
如果您有这种模式:
<div *ngFor="for item in items">
<!-- needs to be one per item -->
<ng-template details-directive></ng-template>
</div>
我建议将指令包装在组件中
@Component({
selector: 'details-wrapper',
template: '<ng-template details-directive></ng-template>'
})
export class DetailsWrapper {
@Input item?: Item;
// Dynamically load details using the regular solution.
}
并将其作为您的for循环:
<div *ngFor="for item in items">
<details-wrapper [item]="item"></details-wrapper>
</div>
答案 3 :(得分:0)
我通过添加'static:false'解决了该问题。
@ViewChild(conf.id,{read:ViewContainerRef,static:false})var widgetTarget:ViewContainerRef