如何动态地将组件作为子组件添加到指令中?
Posted
技术标签:
【中文标题】如何动态地将组件作为子组件添加到指令中?【英文标题】:How to dynamically add a component as a child to a directive? 【发布时间】:2016-12-16 02:33:30 【问题描述】:我一直在试验 Angular 2,我已经能够通过获取现有子级的 @ViewChild 然后使用 ComponentResolver 添加我的动态组件来动态地将一个组件添加到另一个子级。
但是,如果您无法控制模板(即您正在动态地将组件添加到指令的子级),您应该怎么做?我不知道我的指令将在容器中包含哪些元素,那么我如何获得类似的 ViewContainerRef 呢?
编辑: 我似乎在获取指令的 @ViewChild 时也遇到了问题。 Here's 我在我的应用程序中发生的事情..
Hello.component.ts
import Component from '@angular/core'
@Component(
selector: 'hello',
template: '<h1>Hi!</h1>',
styles: ['h1background-color: green']
)
export class HelloComponent
Test.directive.ts
import Directive, ViewChild, ViewContainerRef, ComponentResolver, OnInit from '@angular/core';
import HelloComponent from './hello.component'
@Directive(
selector: '[testDir]'
)
export class TestDirective implements OnInit
@ViewChild('div', read: ViewContainerRef) div;
constructor(private viewContainerRef: ViewContainerRef, private componentResolver: ComponentResolver)
ngOnInit()
this.componentResolver.resolveComponent(HelloComponent).then((factory) =>
this.div.createComponent(factory);
this.viewContainerRef.createComponent(factory);
);
app.component.ts
import Component from '@angular/core';
import TestDirective from './app.directive';
import HelloComponent from './hello.component'
@Component(
selector: 'my-app',
template: `
<div testDir>
<div #div></div>
</div>
`,
directives: [TestDirective, HelloComponent]
)
export class AppComponent
【问题讨论】:
【参考方案1】:您可以使用Renderer2
服务将组件添加到指令的子级。
此示例使用新创建的组件的元素引用,并通过渲染服务将其附加到当前元素引用。
下面是一个在点击它时执行的指令,你也可以在 onInit 上执行相同的操作:
@Directive(
selector: '[mydirective]'
)
export class MyDirective
constructor(
private cfResolver: ComponentFactoryResolver,
public vcRef: ViewContainerRef,
public elementRef: ElementRef,
private renderer: Renderer2
)
@HostListener('click', ['$event'])
onClick()
const factory =
this.cfResolver.resolveComponentFactory(HelloComponent);
const componentRef = this.vcRef.createComponent(factory);
this.renderer.appendChild(
this.vcRef.element.nativeElement,
componentRef.injector.get(HelloComponent).elementRef.nativeElement
);
您还可以在将 Dynamic 组件附加到当前宿主元素之前设置其任何 Input
属性。
【讨论】:
elementRef 不存在,必须作为公共添加到 HelloComponent 的构造函数中:constructor(public elementRef: ElementRef) 附加“componentRef.instance.elementRef.nativeElement”而不是“componentRef.injector.get(HelloComponent).elementRef.nativeElement”有什么区别吗?我发现两者都可以工作 如果 renderer.appendChild 没有完成,组件将被附加到应用指令的父节点(参见github.com/angular/angular/issues/30743)以上是关于如何动态地将组件作为子组件添加到指令中?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 React 中的 CSS 模块将多个类动态传递给子组件
如何根据另一个组件的存在有条件地将类添加到 Magnolia 组件模板?