Angular 2.0 final:如何从代码中实例化组件

Rob*_*bba 8 angular

我正在寻找一种方法来从另一个组件的代码中实例化Angular2中的组件.与许多提出类似问题的人不同,我对动态编译新组件并不感兴趣,只是实例化并插入已存在于我的应用程序中的组件.

例如:

说我有两个组成部分:

仪表板item.component.ts

import { Component } from "@angular/core";

@Component({
    selector: "dashboard-item",
    template: "Some dashboard item with functionality"
})
export class DashboardItemComponent {
    constructor() {}

    onInit() {}
}
Run Code Online (Sandbox Code Playgroud)

dashboard.component.ts

import { Component } from "@angular/core";

@Component({
    selector: "dashboard",
    template: "<h1>Dashboard!</h1><div #placeholder></div>"
})
export class DashboardComponent {
    constructor() {}

    onInit() {}
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是一种在DashboardComponent的onInit中创建DashboardItemComponent并将其添加到#placeholder div的方法.

有两点需要注意:

这两个早期的问题提出了类似的问题,但他们的答案要么相当平淡,要么与Angular2的早期(beta)版本相关,而且似乎不再起作用.

mxi*_*xii 16

这是一个有效的演示:https://plnkr.co/edit/pgkgYEwSwft3bLEW95Ta?p = preview

import {Component, NgModule, ViewChild, ElementRef, Input, Output, EventEmitter, ViewContainerRef, ComponentRef, ComponentFactoryResolver, ReflectiveInjector} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'any-comp',
  template: '<div (click)="clicked.emit($event)">here i am.. {{name}}</div>'
})
export class AnyComponent {

  @Input() name;
  @Output() clicked = new EventEmitter();

  constructor() {
    console.log('some1 created me.. ! :)');
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <template #placeHolder>
      </template>
    </div>
  `,
})
export class App {

  @ViewChild('placeHolder', {read: ViewContainerRef}) private _placeHolder: ElementRef;

  name:string;
  constructor(private _cmpFctryRslvr: ComponentFactoryResolver) {
    this.name = 'Angular2'
  }

  ngOnInit() {
    let cmp = this.createComponent(this._placeHolder, AnyComponent);

    // set inputs..
    cmp.instance.name = 'peter';

    // set outputs..
    cmp.instance.clicked.subscribe(event => console.log(`clicked: ${event}`));

    // all inputs/outputs set? add it to the DOM ..
    this._placeHolder.insert(cmp.hostView);
  }

  public createComponent (vCref: ViewContainerRef, type: any): ComponentRef {

    let factory = this._cmpFctryRslvr.resolveComponentFactory(type);

    // vCref is needed cause of that injector..
    let injector = ReflectiveInjector.fromResolvedProviders([], vCref.parentInjector);

    // create component without adding it directly to the DOM
    let comp = factory.create(injector);

    return comp;
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, AnyComponent ], // ! IMPORTANT
  entryComponents: [ AnyComponent ], // ! IMPORTANT --> would be lost due to Treeshaking..
  bootstrap: [ App ]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果有人想避免接受答案中的任何陈述,这里是片段

    public createComponent<T>(vCref: ViewContainerRef, type: Type<T>): ComponentRef<T> {

      let factory = this._cmpFctryRslvr.resolveComponentFactory(type);

      // vCref is needed cause of that injector..
      let injector = ReflectiveInjector.fromResolvedProviders([], vCref.parentInjector);

      // create component without adding it directly to the DOM
      let comp = factory.create(injector);

      return comp;
    }
Run Code Online (Sandbox Code Playgroud)