ComponentResolver实现(删除不推荐使用的dynamiccomponentloader)

时间:2016-06-23 08:30:10

标签: angular

我正在尝试将组件动态加载到另一个组件中。在测试版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创建的。

0 个答案:

没有答案