Angular 2 innerHTML (click) binding
NickName:Paul Leclerc Ask DateTime:2016-06-07T18:23:49

Angular 2 innerHTML (click) binding

I had such a large html menu that I decided to binding to be able to make several submenu dropdown and avoid html code duplication. Parent > child (which is parent too) > child...

For the context : In ng2_msList/msList.components.ts, ColumnsManagements.ts is imported as this.ColumnsManagementInstance. The innerHTML menu is displayed properly, in ng2_msList/pages/list.html :

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

With (in a very simplified version of my code) : (Thanks to this 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)" (previously in the html content) is not working anymore. It's writing in the view as simple text in tag (before the innerHtml it was not displayed).

I can't reach a way to make it works again. I test multiple ways to call the function or as I found in web links as on the Ang Doc Section, here for example. These examples call a function which is set in the same file/context very easily (click)="MyAction()" but with my context I can't get a way to call it properly.

The app architecture is maybe be not as Angular2 click call would expect.

Copyright Notice:Content Author:「Paul Leclerc」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/37676726/angular-2-innerhtml-click-binding

Answers
Wilt 2020-03-18T17:34:58

There are two solutions I know to this problem:\n\n1) Using the Renderer2 to add click events on rendering\n\nIn this solution the Renderer2 is used to add a click event listener to the element and filter target by its type HTMLAnchorElement.\n\npublic ngOnInit() {\n // Solution for catching click events on anchors using Renderer2:\n this.removeEventListener = this.renderer.listen(this.elementRef.nativeElement, 'click', (event) => {\n if (event.target instanceof HTMLAnchorElement) {\n // Your custom anchor click event handler\n this.handleAnchorClick(event);\n }\n });\n}\n\n\nStackBlitz with a demo\n\n2) Using ElementRef and querySelectorAll after view init\n\nIn this solution all anchor elements are found from the ElementRef using querySelectorAll and add a custom click handler is added. This has to be done after view initialization so the DOM is rendered and we can query the rendered element.\n\npublic ngAfterViewInit() {\n // Solution for catching click events on anchors using querySelectorAll:\n this.anchors = this.elementRef.nativeElement.querySelectorAll('a');\n this.anchors.forEach((anchor: HTMLAnchorElement) => {\n anchor.addEventListener('click', this.handleAnchorClick)\n })\n}\n\n\nStackBlitz with a demo\n\n\n\nNOTE Please leave a comment on which solution you prefer and why, I actually have a hard time choosing which one I like more.",


hzitoun 2018-01-30T14:29:10

It may be too late but let me hope that is going to help someone. \n\nSince you want click binding (and probably other bindings) it would be better to skip using [innerHTML]=\"...\" and create an inner component to which you pass the data via @Input() annotation. \n\nConcretely, image you have a component called BaseComponent where you set some HTML code to a variable htmlData :\n\nlet htmlData = '...<button (click)=\"yourMethodThatWontBeCalled()\">Action</button>...'\n\n\nThen in BaseComponent's html file you bind it like below:\n\n...<div [innerHTML]=\"htmlData\"></div>...\n\n\nInstead of doing this, you create InnerComponent.ts :\n\n@Component({\n selector: 'inner-component',\n templateUrl: './inner-component.html',\n styleUrls: ['./inner-component.scss']\n})\nexport class InnerComponent {\n @Input()\n inputData: any;\n\n methodThatWillBeCalled(){\n //do you logic on this.inputData\n }\n}\n\n\nInnerComponent's Html file:\n\n...<button (click)=\"methodThatWillBeCalled()\">Action</button>...\n\n\nNow in BaseComponent's Html file:\n\n...<inner-component [inputData]=\"PUT_HERE_YOUR_DATA\"></inner-component>\n",


Ihor Khomiak 2019-06-06T19:27:05

in CSS:\n\n.dropdown-menu {\n pointer-events: none;\n}\n\n\nIt will solve an issue with innerHTML (click) binding.",


jamesthe500 2019-03-28T03:15:27

I was able to set up click listeners for html that came from an API to innerHtml.\n\nThe html from the API needed to be wrapped in a div set to not display.\n\n<div id='wholeHtml' style='display:none;'>\n <h2>Foo Bar Inc.</h2>...\n <button class="buttonToClick">Click me</button>\n</div>\n\n\nThe template where the html landed, also needed to be wrapped in targetable div. Note the 'safeHtml' pipe that told Angular that this source was to be trusted (this was an API that I managed).\n\n<div id="parentDiv">\n <div [innerHTML]="apiData | safeHtml"></div>\n</div>`\n\n\nThe corresponding component used ElementRef and Renderer2 to copy the hidden div from the api (which was prevented from accepting a click listener), paste it into the parent div, set the newly pasted content to display, and apply click listeners.\n\nimport { Component, OnInit, ElementRef, Renderer2 } from '@angular/core';\n ...\n \nexport class ExampleComponent implements OnInit {\n constructor(private elRef: ElementRef, private renderer: Renderer2) {}\n ngOnInit() {}\n ngAfterViewInit() {\n if(document.getElementById('wholeHtml')){\n let allContent = this.elRef.nativeElement.querySelector('#wholeHtml');\n let parentContainer = this.elRef.nativeElement.querySelector('#parentDiv');\n this.renderer.appendChild(parentContainer, allContent);\n this.renderer.removeStyle(allContent, "display");\n let clickButtons = this.elRef.nativeElement.querySelectorAll('.buttonToClick');\n for(var i = 0; i < clickButtons.length; i++){\n this.renderer.listen(clickButtons[i], 'click', function($event){\n functionToCall($event.target); \n });\n };\n }\n }\n ngOnDestroy() {\n this.renderer.destroy();\n }\n }\n\nI was using Angular 6, for what it's worth.",


Casper Nybroe 2021-09-14T17:53:49

Using the solution from Ihor:\nWrap the tag using [innerHtlm] in another tag, set pointer-events: none on the child tag and set the click() event on the parent tag:\n<div (click)="doSomething()">\n <div style="pointer-events:none" [innerHtlm]="someValue">\n</div>\n",


Günter Zöchbauer 2016-06-07T10:28:47

That's by design. Angular doesn't process HTML added by [innerHTML]=\"...\" (except sanitization) in any way. It just passes it to the browser and that's it.\n\nIf you want to add HTML dynamically that contains bindings you need to wrap it in a Angular2 component, then you can add it using for example ViewContainerRef.createComponent()\n\nFor a full example see Angular 2 dynamic tabs with user-click chosen components\n\nA less Angulary way would be to inject ElementRef, accessing the added HTML using \n\nelementRef.nativeElement.querySelector('a').addEventListener(...)\n",


More about “Angular 2 innerHTML (click) binding” related questions

Angular 2 innerHTML (click) binding

I had such a large html menu that I decided to binding to be able to make several submenu dropdown and avoid html code duplication. Parent > child (which is parent too) > child... For the context...

Show Detail

Angular 2 innerHTML (click) binding

I had such a large html menu that I decided to binding to be able to make several submenu dropdown and avoid html code duplication. Parent > child (which is parent too) > child... For the context...

Show Detail

Angular 2 innerHTML (click) binding

I had such a large html menu that I decided to binding to be able to make several submenu dropdown and avoid html code duplication. Parent > child (which is parent too) > child... For the context...

Show Detail

Download scripts inside Angular 2 innerHTML binding

I'm working on an Angular 2 application that is showing news items inside my application. The news items are saved in a database and loaded into the template using Angular's [innerHTML] binding. A

Show Detail

Angular 2 binding/events not working when adding template as innerHTML

I am trying to create a reusable table which can be configurable. The cells can be configured to have html template. I am configuring the column "Review" to have html template with anchor tag with...

Show Detail

Angular 2 binding/events not working when adding template as innerHTML

I am trying to create a reusable table which can be configurable. The cells can be configured to have html template. I am configuring the column "Review" to have html template with anchor tag with...

Show Detail

Angular 7 add innerHTML dynamically binding

I am trying to set up a system which loads the html page from a stored html file and renders it with angular. How to bind property and event in this file, I'm trying to inject it with innerHTML.

Show Detail

Property Binding [innerHTML] is removing the anchor tag functionality in angular 4 data binding

Hi, The property binding [innerHTML] takes only the text in between the raw html tags and the anchor tag functionality is not getting applied for data binding. So i want the anchor tag functionality

Show Detail

Binding (click) in [innerhtml] with angular (ionic) for mention @ or Hashtags #

Hi try to dinamically add link to some part of a text submit by a user like : submitText = '#test @mention http://google.com' Rendering html : [innerHTML]="submitText | dynamiccontent" But re...

Show Detail

Style not rendering in innerHTML in Angular2

I am developing a page in Angular2/4 which has a left navigation bar. I put this left menu in a separate component and nesting this in the main component. Reason being I need to reuse this left men...

Show Detail