2016-09-25 21 views
8

別のコンポーネントのコード内からAngular2のコンポーネントをインスタンス化する方法を探しています。同様の質問をした多くの人々とは違って、私は新しいコンポーネントを動的にコンパイルすることにそれほど関心を持っていません。アプリケーションに既に存在するインスタンスをインスタンス化して挿入するだけです。例えばAngular 2.0 final:コードからコンポーネントをインスタンス化する方法

ダッシュボードitem.component.ts

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

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

    onInit() {} 
} 

dashboard.component.ts

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

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

    onInit() {} 
} 

は、私は2つの要素を持っていると言います

私が探しているのは、DashboardComponentのonInitにDashboardItemComponentを作成し、それを#placeholder divに追加する方法です。注意すべき

2つのこと:

をこれら二つの以前の問題は、同様の質問をするが、その答えはどちらかという精彩を欠いていないか、Angular2の以前の(ベータ)版に関連して、もはや機能しているようです。 How to instantiate and render Angular2 components?

+0

あなたがのためにhttp://stackoverflow.com/questions/39678963/load-existing-components-dynamically-angular-2-final-release/39680765#39680765 – yurzui

答えて

11

はここで働いてデモです: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 {} 
+0

おかげでから最初のオプションを見てみることができます入力、これは確かに役立ちます。 entryComponentsはtreeshakingのために重要であると言います。私はそれが何を意味するかは分かりませんが、それがなければ機能しません。 Angularがコンパイルを実行するときに、このトレシェーキングプロセスは常に実行されますか? – Robba

+0

のように、はい。それは決してどこでもインスタンス化されないので、最適化され、削除されます。 – mxii

1

あなたは親コンポーネント内部のあなたの子コンポーネントを配置することができます。

<parent-component> 
    <child-component></child-component> 
</parent-component> 

子コンポーネントは、イベント発生時にイベントを発生させるEventEmitterプロパティを公開します。親はそのイベントプロパティにバインドし、それらのイベントに反応します。 https://angular.io/docs/ts/latest/cookbook/component-communication.html

0

MXIIの答えに記載されているもののためにやって(?新)API関数があるようです。 ViewContainerRefにはcreateComponentメソッドがあります。コンポーネントをインスタンス化してビューに追加します。

let factory = this._cmpFctryRslvr.resolveComponentFactory(AnyComponent); 
let cmp = this.viewContainer.createComponent(factory); 
cmp.instance.name = 'peter'; 
関連する問題