Angular 2 innerHTML (щелчок) привязка

У меня было такое большое html-меню, которое я решил привязать, чтобы иметь возможность выпустить несколько подменю и избежать дублирования кода HTML. Родительский > дочерний (родительский) > дочерний...

В контексте: В ng2_msList/msList.components.ts импортируется ColumnsManagements.ts как this.ColumnsManagementInstance. Меню innerHTML отображается правильно, в ng2_msList/pages/list.html:

<!-- COLUMNS DROPDOWN BUTTON -->
<ul [innerHTML]="msList.ColumnsManagementInstance.columnMenu" class="dropdown-menu" role="menu"> </ul>

С (в очень упрощенной версии моего кода): (Благодаря этому Stack Q)

setHtmlColumnsMenu() {
     var self = this;
     var htmlcolumnsmenu = '';
     [...]
     htmlcolumnsmenu += this.createColumnsList(this.getNoneRelationalColumns(true));

     // which return something like a lot of html content and sometime in it : 
     // <a href="javascript:;" (click)="msList.ColumnsManagementInstance.toogleColumn(column)">
     [...]
     return htmlcolumnsmenu;
}

BUT (click) = "msList.ColumnsManagementInstance.toogleColumn(column)" (ранее в html-контенте) больше не работает. Он писал в представлении как простой текст в теге (до innerHTML он не отображался).

Я не могу найти способ сделать это снова. Я тестирую несколько способов вызова функции или, как я нашел в веб-ссылках, как на раздел Ang Doc, здесь. Эти примеры называют функцию, которая очень легко устанавливается в том же файле/контексте (щелкните) = "MyAction()", но в моем контексте я не могу получить способ правильно ее называть.

Архитектура приложения может быть не такой, как Angular2 ожидание вызова.

Ответы

Ответ 1

Это по дизайну. Angular не обрабатывает HTML, добавленный с помощью [innerHTML]="..." (кроме санировки) любым способом. Он просто передает его в браузер и что он.

Если вы хотите добавить HTML динамически, который содержит привязки, вам нужно обернуть его в компонент Angular2, затем вы можете добавить его, используя, например, ViewContainerRef.createComponent()

Для полного примера см. Angular 2 динамических вкладки с выбранными вами компонентами с кликом

Менее интерактивным способом было бы ввести ElementRef, получив добавленный HTML, используя

elementRef.nativeElement.querySelector('a').addEventListener(...)

Ответ 2

Возможно, слишком поздно, но я надеюсь, что это поможет кому-то.

Так как вы хотите привязку привязки (и, возможно, другие привязки), лучше пропустить, используя [innerHTML]="..." и создать внутренний компонент, с которым вы передаете данные через @Input() аннотация.

Конкретно, у изображения есть компонент с именем BaseComponent, где вы устанавливаете некоторый код HTML для переменной htmlData​​strong > :

let htmlData  = '...<button (click)="yourMethodThatWontBeCalled()">Action</button>...'

Затем в BaseComponent html файле вы привязываете его, как показано ниже:

...<div [innerHTML]="htmlData"></div>...

Вместо этого, вы создаете InnerComponent.ts:

@Component({
 selector: 'inner-component',
 templateUrl: './inner-component.html',
 styleUrls: ['./inner-component.scss']
})
export class InnerComponent {
   @Input()
   inputData: any;

   methodThatWillBeCalled(){
    //do you logic on this.inputData
   }
}

InnerComponent Html файл:

...<button (click)="methodThatWillBeCalled()">Action</button>...

Теперь в BaseComponent Html файле:

...<inner-component [inputData]="PUT_HERE_YOUR_DATA"></inner-component>

Ответ 3

Мне удалось настроить прослушиватели кликов для html, которые пришли из API в innerHtml.

  1. HTML-код из API должен был быть заключен в набор div, чтобы он не отображался.

    <div id='wholeHtml' style='display:none;'> <h2>Foo Bar Inc.</h2>... <button class="buttonToClick">Click me</button> </div>

  2. Шаблон, в который попал html, также нужно было обернуть в target. Обратите внимание на канал " safeHtml ", который сообщает Angular, что этому источнику нужно доверять (это был API, которым я управлял).

    <div id="parentDiv"> <div [innerHTML]="apiData | safeHtml"></div> </div>

  3. В соответствующем компоненте использовались ElementRef и Renderer2 для копирования скрытого элемента div из API (который не позволял принимать прослушиватель щелчков), вставки его в родительский элемент div, настройки отображения недавно вставленного содержимого и применения прослушивателей щелчков.

    import { Component, OnInit, ElementRef, Renderer2 } from '@angular/core';...

    export class ExampleComponent implements OnInit { constructor(private elRef: ElementRef, private renderer: Renderer2) {} ngOnInit() {} ngAfterViewInit() { if(document.getElementById('wholeHtml')){ let allContent = this.elRef.nativeElement.querySelector('#wholeHtml'); let parentContainer = this.elRef.nativeElement.querySelector('#parentDiv'); this.renderer.appendChild(parentContainer, allContent); this.renderer.removeStyle(allContent, "display"); let clickButtons = this.elRef.nativeElement.querySelectorAll('.buttonToClick'); for(var я = 0; я < clickButtons.length; i++){ this.renderer.listen(clickButtons[i], 'click', function($event){ functionToCall($event.target); }); }; } } ngOnDestroy() { this.renderer.destroy(); } }

Я использовал Angular 6, для чего это стоит.

Ответ 4

в CSS:

.dropdown-menu {
  pointer-events: none;
}

Это решит проблему с привязкой innerHTML (click).