这是代码
app.component
import {Component,ViewChild,ViewContainerRef,ComponentFactoryResolver} from '@angular/core'; import {NewChildComponent} from "./newChild.component"; @Component({ selector: 'app-main',templateUrl: 'app.component.html' }) export class AppComponent { @ViewChild('captureElement',{read: ViewContainerRef}) captureElement: ViewContainerRef; constructor (private componentFactoryResolver: ComponentFactoryResolver) { var childComponent = this.componentFactoryResolver.resolveComponentFactory(NewChildComponent); var myArea = document.getElementById('myArea'); var myRow = document.createElement("div"); myArea.appendChild(myRow); //I want to add the capture element #myCapture as a child of myRow //Add something like this <div #captureElement></div> programmatically through JS/TS // How can I do this? // I then create the component this.parent.createComponent(NewChildComponent); }
app.component.html
<div id="myArea"> <!-- Static way of doing it --> <!--<div #captureElement></div>--> </div>
我想在父组件中动态创建它并使其成为子组件,而不是在将要插入子组件的#captureElement中静态定义.
以下是我在提出这个问题之前提到的一系列问题
> Angular2: Insert a dynamic component as child of a container in the DOM
> How to place a dynamic component in a container
> Angular 2 dynamic tabs with user-click chosen components
尝试过几件事
>尝试使用#captureElement创建一个div元素
以编程方式属性,但不起作用.
>尝试以编程方式创建随机元素,并使用ViewContainerRef来查找它.这也行不通.
在2.3.0中,引入了attachView,它允许您将更改检测附加到ApplicationRef.您可以创建一些类来封装您的逻辑,如:
export class HtmlContainer { private attached: boolean = false; private disposeFn: () => void; constructor( private hostElement: Element,private appRef: ApplicationRef,private componentFactoryResolver: ComponentFactoryResolver,private injector: Injector) { } attach(component: Type<any>) : ComponentRef<any> { if(this.attached) { throw new Error('component has already been attached') } this.attached = true; const childComponentFactory = this.componentFactoryResolver.resolveComponentFactory(component); let componentRef = childComponentFactory.create(this.injector); this.appRef.attachView(componentRef.hostView); this.disposeFn = () => { this.appRef.detachView(componentRef.hostView); componentRef.destroy(); }; this.hostElement.appendChild((componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]); return componentRef; } dispose() { if(this.attached) { this.disposeFn(); } } }
这个班只是帮助
1)解析您的动态组件
this.componentFactoryResolver.resolveComponentFactory(component);
2)然后通过调用compFactory.create来编译组件
3)之后通过调用上面提到的appRef.attachView来注册其changeDetector(componentRef.hostView扩展ChangeDetectorRef)(否则更改检测将不适用于您的组件)
4)最后将组件的rootNode附加到host元素
this.hostElement.appendChild((componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]);
您可以按如下方式使用它:
@Component({ selector: 'my-app',template: `<div id="myArea"></div> `,entryComponents: [NewChildComponent] }) export class AppComponent { containers: HtmlContainer[] = []; constructor( private appRef: ApplicationRef,private injector: Injector) { } ngOnInit() { var myArea = document.getElementById('myArea'); var myRow = document.createElement("div"); myArea.appendChild(myRow); this.addComponentToRow(NewChildComponent,myRow,'test1'); this.addComponentToRow(NewChildComponent,'test2'); } addComponentToRow(component: Type<any>,row: HTMLElement,param: string) { let container = new HtmlContainer(row,this.appRef,this.componentFactoryResolver,this.injector); let componentRef = container.attach(component); componentRef.instance.param1 = param; this.containers.push(container); } ngOnDestroy() { this.containers.forEach(container => container.dispose()); } }
也可以看看
> Angular2 – Component into dynamicaly created element
> Angular2 Dynamic Component Injection in Root
> https://github.com/angular/material2/blob/2.0.0-beta.1/src/lib/core/portal/dom-portal-host.ts#L30-L86(你可以在这里找到角度< 2.3.0的后备)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。