2016-10-25 2 views
10

У меня есть рекурсивная древовидная структура, содержащая узлы, каждая из которых имеет свойство «htmlStringContent». Когда я отображение дерева с использованием вложенных компонентов «узел» и попытаться представить содержание HTML я использую:Динамически отображать элементы, содержащие HTML с функциями (click) Angular 2

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

HTML-дисплеи правильно, но для следующих элементов:

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

В (нажмите) функции не работают. Я знаю, что у этого есть previously been posted, но с большим количеством обновлений угловой вывел недавно я не могу найти какие-либо решения. This answer заставляет меня поверить, что я должен использовать директиву ngComponentOutlet, но я не уверен, как это сделать.

Как я могу получить угловое связывание этой функции щелчка?

Редактировать: Мне сказали использовать ComponentFactoryResolver, но не вижу, как я могу использовать это, чтобы правильно отображать html. Может ли кто-нибудь помочь?

Edit2: Я разбор «htmlStringContent» через дезинфицирующую трубу перед выводом его на [innerHtml]

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

Edit3: В основном этот вопрос спрашивает, является ли это, как все можно отображать HTML от собственности на объект в угловом 2/ионном 2, сохраняя при этом функциональность (щелчок). Я также открыт для обходных ответов.

+0

Этот клик по клику не будет работать. У вас есть компонент создания, и вы сможете генерировать событие клика, как показано на одной из ваших ссылок. – 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

I видеть, что это динамически создает компоненты ..но у меня уже есть вложенная структура компонентов, которые отображаются с использованием рекурсивного 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() на модуль и получить необходимую вам фабрику компонентов. Тогда это вопрос рендеринга его в DOM с помощью метода ViewContainerRef.createComponent().

Здесь работает plunker: dynamic template component

Имейте в виду, однако, что - на данный момент - этот подход может быть использован только с JIT компиляции. В компиляции AOT угловой компилятор недоступен, и попытка его использования выдает ошибку.

Смежные вопросы