2016-10-25 9 views
10

私は、それぞれが 'htmlStringContent'プロパティを持つノードを含む再帰的なツリー構造を持っています。私は、ネストされた「ノード」のコンポーネントを使用してツリーを表示し、HTMLコンテンツを提示しようとすると私が使用します。HTMLを含む要素を動的に表示する機能(クリック)角度2

<div [innerHtml]="node.htmlStringContent"></div> 

HTMLが正しく表示が、次の要素のために:

<a (click)="function()">click me</a> 

(クリック)機能動作しません。私はこれがpreviously been postedを持っていることを知っていますが、角度の更新が最近大量に更新されたので、私は解決策を見つけることができません。 This answerは、ngComponentOutletディレクティブを使用しているはずだと私に信じていますが、どういうわけかはわかりません。

このクリック機能をバインドする方法を教えてください。

編集:私はComponentFactoryResolverを使用するように言われていますが、これを使ってhtmlを正しく表示する方法がわかりません。誰も助けを提供することはできますか?

EDIT2:私は[innerHTMLプロパティ]でそれを表示する前に消毒パイプを通して「htmlStringContent」を解析しています

transform(v: string) : SafeHtml { 
    return this._sanitizer.bypassSecurityTrustHtml(v); 
} 

EDIT3:基本的に、この質問は、財産上からHTMLを表示するようにすべての可能性であるかどうかを尋ねています角度2 /イオン2のオブジェクトは、その上に(クリック)機能を保持します。私は回避策の回答にもオープンしています。

+0

このようなクリックイベントは機能しません。あなたはコンポーネントを作成しているので、リンクの1つに既に表示されているようにクリックイベントを生成することができます。 – micronyks

+0

@micronyksしかし、私はまだ[innerHtml]を使ってHTMLコンテンツを提示する必要がありますか? – alsco77

+1

angular1のように、angular2には '$ compile'サービスがないので、あなたは' componentFactoryResolver'を使ってそれを行うことができます。 – micronyks

答えて

4

CFRのDEMO:https://plnkr.co/edit/jKEaDz1JVFoAw0YfOXEU?p=preview

@Component({ 
    selector: 'my-app', 
    template: ` 

    <button (click)="addComponents()">Add HTML (dynamically using CRF)</button> 

    <h1>Angular2 AppComponent</h1> 
    <hr> 

    <div> 
    <h5>dynamic html goes here</h5> 
     <div class="container"> 
     <template #subContainer1></template> 
     </div> 
    </div> 


    `, 

}) 
export class App { 
    name:string; 
    @ViewChild('subContainer1', {read: ViewContainerRef}) subContainer1: ViewContainerRef; 

    constructor(
     private compFactoryResolver: ComponentFactoryResolver 
    ) { 
     this.name = 'Angular2' 
    } 

    addComponents() { 

     let compFactory: ComponentFactory; 

     compFactory = this.compFactoryResolver.resolveComponentFactory(Part1Component); 
     this.subContainer1.createComponent(compFactory); 

    } 
    } 
+0

を使用することができます私はこれがコンポーネントを動的に作成することを確認してください。再帰的なngforを使用して表示されるコンポーネントのネストされた構造を既に持っています。このソリューションは、コンポーネントプロパティに含まれるHTML文字列をどのように表示し、クリック機能を含めて正しく表示しますか? – alsco77

3

私が正しく理解していれば、あなたは動的なテンプレートを使用して、実行時にそれらをコンパイルする必要があります。もしそうなら、あなたは、角度のコンパイラを使用する必要があります。

@Component({ 
    selector: 'my-app', 
    template: ` 
     <h1>Angular 2 Dynamic Component</h1> 
     <template #container></template> 
    ` 
}) 
export class AppComponent implements AfterContentInit, OnDestroy { 
    private dynamicComponentRefs: ComponentRef[] = []; 

    @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef; 

    constructor(private resolver: ComponentFactoryResolver, 
       private compiler: Compiler) {} 

    ngAfterContentInit() { 
    let html = ` 
     <div>Always Visible</div> 
     <div [hidden]="clause1">Hidden because of clause1 = true</div> 
     <div [hidden]="clause2">Visible because of clause2 = false</div> 
     <button type="button" (click)="buttonClicked()">Click me!</button> 
     <div *ngIf="clicked">You clicked the button!</div> 
    `; 

    this.compiler.compileModuleAndAllComponentsAsync(createDynamicComponent(html)) 
     .then((mwcf: ModuleWithComponentFactories) => { 
      let factory: ComponentFactory = mwcf.componentFactories.find(cf => 
      cf.componentType.name === 'DynamicComponent'); 
      this.dynamicComponentRefs 
       .push(this.container.createComponent(factory)); 
     }); 
    } 

    ngOnDestroy() { 
    /* Make sure you destroy all dynamically created components to avoid leaks */ 
    this.dynamicComponentRefs.forEach(dcr => { 
     dcr.destroy(); 
    }); 
    } 

} 

export function createDynamicComponent(html: string): Type<NgModule> { 
    @Component({ 
    template: html, 
    }) 
    class DynamicComponent { 
    private clause1: boolean = true; 
    private clause2: boolean = false; 
    private clicked = false; 

    buttonClicked() { 
     this.clicked = true; 
    } 
    } 

    @NgModule({ 
    imports: [CommonModule], 
    declarations: [DynamicComponent], 
    }) 
    class DynamicComponentModule {} 

    return DynamicComponentModule; 
} 

を基本的には、動的に(例えばスルー機能)を宣言するコンポーネントおよびモジュールを作成し、引数としてそれをテンプレートに渡す必要があります。その後、モジュール上でcompileModuleAndAllComponentsAsync()と呼び出して、必要なコンポーネントファクトリを取得することができます。それでは、ViewContainerRef.createComponent()メソッドを通してDOMにレンダリングすることです。ここで

はplunkerに取り組んでいる:dynamic template component

があることに留意してください - このアプローチでは、唯一のJITコンパイルで使用することができます - 今のところ。 AOTコンパイルでは、角度コンパイラは使用できず、使用しようとするとエラーが発生します。

関連する問題