如何将组件作为子项动态添加到指令中?

时间:2016-08-09 21:51:27

标签: angular

我一直在尝试Angular 2,我已经能够通过获取现有孩子的@ViewChild,然后使用ComponentResolver添加我的动态组件,动态地将组件添加到另一个孩子的孩子。

但是,如果您无法控制模板(即,您是否正在向指令的子项添加组件),您应该怎么做?我不知道我的指令在容器中会有哪些元素,那么我如何获得类似的东西的ViewContainerRef呢?

编辑:我似乎也遇到了获取指令的@ViewChild的问题。 Here's我在我的应用中发现了一些内容......

Hello.component.ts

import { Component } from '@angular/core'

@Component({
  selector: 'hello',
  template: '<h1>Hi!</h1>',
  styles: ['h1{background-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 个答案:

答案 0 :(得分:0)

您可以使用Renderer2服务将组件添加到指令的子代中。

此示例使用新创建组件的元素引用,并通过使用渲染服务将其附加到当前元素ref。

下面是一个执行该指令的指令,您也可以在onInit上执行相同的操作:

@Directive({
  selector: '[mydirective]'
})
export class MyDirective {
  constructor(
    private cfResolver: ComponentFactoryResolver,
    public vcRef: ViewContainerRef,
    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
    );
  }
}

在将动态组件附加到当前宿主元素之前,您还可以设置其任何Input属性。