我正在尝试将组件动态加载到另一个组件中。在测试版14之前,我们使用了DynamicComponentLoader.loadIntoLocation
,但由于现在不推荐使用它,我们正在寻找实例化组件的新方法。
我看到ComponentResolver and ViewContainerRef
方式,但我无法直接使用该解决方案。
我们正在使用GoldenLayout为我们的网页实现对接功能。因此,由goldenlayout创建的容器通过jQuery动态注入DOM,因此我无法使用@ViewChild
获取ViewContainerRef
的引用并将其与新方法一起使用。
我找到了一种用DynamicComponentLoader.loadAsRoot
做我想要的方式:
container.getElement().html(`<div id='component${Component.componentCount}'></div>`);
this.dynamicComponentLoader.loadAsRoot(Component,selector,this.injector)
.then((componentRef:ComponentRef<Component>)=>{
container.compRef = componentRef
(<any>this.applicationRef)._loadComponent(componentRef);
if(componentRef.instance.ngOnChanges){
componentRef.instance.ngOnChanges();
}
return componentRef;
});
选择器是我们使用.getElement().html()
动态添加的选择器。
但是我不喜欢这种实现它的方式,因为我使用的是现在已弃用的DynamicComponentLoader
,也是因为
(<any>this.applicationRef)._loadComponent(componentRef);
用于&#34;傻瓜&#34;转换器是为了使用_loadComponent()
未公开的ApplicationRef
。
所以我基本上在寻找一种在运行时动态检索ViewContainerRef
的方法。或者更优雅的方式来实现我所做的(即没有弃用或隐藏的功能)。
如果我没有正确解释自己以及是否有任何不明确的地方,请告诉我。
提前谢谢。
大卫。
编辑:
我的指令现在正在运作:
import { Directive,Component, OnInit ,ApplicationRef, ElementRef,ComponentRef,Type,Input,SimpleChange,DynamicComponentLoader,Injector} from '@angular/core';
import { TestaComponent } from '../testa/testa.component'
import { TestbComponent} from '../testb/testb.component'
declare var GoldenLayout : any;
declare var $ : JQueryStatic;
@Directive({
selector: '[goldenlayout]',
})
export class GoldenLayoutComponent{
@Input() glConfig : any;
private myLayout : any;
static componentCount : number = 0;
constructor(private applicationRef:ApplicationRef, private elementRef : ElementRef,private dynamicComponentLoader:DynamicComponentLoader,private injector: Injector) {}
ngOnInit(){
let goldenConfig = this.glConfig || {
content:[{
type:'row',
content:[
]
}]
};
this.glConfig = goldenConfig;
this.myLayout = new GoldenLayout(goldenConfig,this.elementRef.nativeElement);
this.myLayout.registerComponent('TestAComponent',(container,componentState)=>{
container.getElement().html("<div id='component" + GoldenLayoutComponent.componentCount +"'></div>");
this.dynamicComponentLoader.loadAsRoot(TestaComponent,"#component"+GoldenLayoutComponent.componentCount,this.injector)
.then((componentRef:ComponentRef<TestaComponent>)=>{
container.compRef = componentRef;
(<any>this.applicationRef)._loadComponent(componentRef);
componentRef.instance["buttonName"]= componentState.buttonName;
if(componentRef.instance.ngOnChanges){
componentRef.instance.ngOnChanges();
}
return componentRef;
});
GoldenLayoutComponent.componentCount ++;
});
this.myLayout.registerComponent('TestBComponent',(container,componentState)=>{
container.getElement().html("<div id='component" + GoldenLayoutComponent.componentCount +"'></div>");
this.dynamicComponentLoader.loadAsRoot(TestbComponent,"#component"+GoldenLayoutComponent.componentCount,this.injector)
.then((componentRef:ComponentRef<TestbComponent>)=>{
container.compRef = componentRef;
(<any>this.applicationRef)._loadComponent(componentRef);
componentRef.instance["color"]= componentState.color;
if(componentRef.instance.ngOnChanges){
componentRef.instance.ngOnChanges();
}
return componentRef;
});
GoldenLayoutComponent.componentCount ++;
});
this.myLayout.init();
this.myLayout.on("itemDestroyed",(item)=>{
if (item.container && item.container.compRef){
this.disposeComp(item.container.compRef);
}
});
this.myLayout.on("windowClosed",(item)=>{
this.applicationRef.tick();
});
}
disposeComp(comp : ComponentRef<any>){
if (comp.instance && comp.instance.ngOnDestroy){
comp.instance.ngOnDestroy();
(<any>this.applicationRef)._unloadComponent(comp);
}
}
addComponent(name : string,option: string){
let newComp : any;
if(name == "TestAComponent"){
newComp = {
type: 'component',
componentName: name,
componentState: {buttonName : option}
};
}else{
newComp = {
type: 'component',
componentName: name,
componentState: {color : option}
};
}
this.myLayout.root.contentItems[ 0 ].addChild(newComp);
}
}
我的HTML:
<div style="margin:5px;">
<button (click)='addComponent("TestAComponent",option)'>Spawn test a</button>
<button (click)='addComponent("TestBComponent",option)'>Spawn test b</button>
<input [(ngModel)]="option" type="text"/>
</div>
<div style="height:800px;" goldenlayout></div>
问题在于,当我调用addComponent函数时,我想用container.getElement().html(
);
创建我想添加组件的元素。
起初我的DOM是这样的:
<div>
<button>Spawn test a</button>
<button>Spawn test b</button>
<input/>
</div>
<div goldenlayout>
<div class="lm_goldenlayout lm_item lm_root"></div>
<div class="lm_item lm_row"></div>
</div>
然后我用其中一个按钮生成一个容器。 而我的DOM就像这样:
<div>
<button>Spawn test a</button>
<button>Spawn test b</button>
<input/>
</div>
<div goldenlayout>
<div class="lm_goldenlayout lm_item lm_root"></div>
<div class="lm_item lm_row">
...
<div class="lm_items">
<div class="lm_content">
<div id="component0" _nghost-mip-3="">
<div _ngcontent-mip-3="">
<button _ngcontent-mip-3="">not set</button>
</div>
</div>
</div>
</div>
...
</div>
</div>
我动态加载的是component0
div中生成的内容,所有带lm_
的元素都是由goldenlayout创建的。