I am trying to dynamically load components into another. Before beta 14, we used DynamicComponentLoader.loadIntoLocation, but since it is now deprecated and removed, we are looking for a new way to create components.
I saw a way ComponentResolver and ViewContainerRef, but I can not use this solution.
We use GoldenLayout to implement docking features on our web page. Thus, containers created by goldenlayout are dynamically inserted into the DOM using jQuery, so I cannot use it @ViewChildto get a link to ViewContainerRefand use it with the new method.
I found a way to do what I wanted with 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);, "" , _loadComponent(), ApplicationRef.
, ViewContainerRef . , ( ).
, , , - .
.
.
Edit:
:
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>
, , , container.getElement().html( ); addComponent.
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>
, div component0, lm_ goldenlayout.