Angular 6 - Add Event handler to dynamically created html element

Viewed 13500

I want to attach a click event to the dynamically created html element. The click event will should be able to fire another method in component.

I have already gone through other SO answers suggesting to use ElementRef to attach event. But, its not working for my case.

I am using mapQuest API to render map. The map will have geocode plotted & it will add a roll over content. To add the rollover content I am using the API method of mapQuest, like info.setInfoContentHTML('<a>click me</a>');

Just for reference: https://developer.mapquest.com/documentation/javascript-api/pois-infowindows/

The link will be inside the popup which will be added to the dom dynamically by plugin when user hover on the icon. How to add event listener on the link which is shown only when the user hover over & there is no callback event provided by plugin which can fire after hover popup is displayed.

I was looking for jQuery live like functionality which would attach event listener though the element is not on the DOM.

3 Answers

Because Angular processes the template when the component is compiled. Any HTML added later is not compiled again and bindings are ignored.

You can use the following :

constructor(private elRef:ElementRef) {}

ngAfterViewInit() {
  // assume dynamic HTML was added before
  this.elRef.nativeElement.querySelector('button').addEventListener('click', 
  this.onClick.bind(this));
}

your use case :

public createElement(){
  
  const el = '<button>click me</button>';
  this.elRef.nativeElement.querySelector('button').addEventListener('click', 
  this.methodName.bind(this));
  info.setInfoContentHTML(el);
}

public methodName(){
    
      console.log('burrah!!! called');
    }

2022 update. :

Stackblitz demo

I tried solution of @programoholic. it works but I need change little bit.
After doing this, there is two problems are,

  1. Fired event could be multiple.(Click "Create button" and check console log)
  2. If button added a lot, you need to check a index at elementList to add event listener.

Here is sample.

btnClicked(){

  //create botton
  let element = document.getElementById(this.uuid);    
  this.buttonHtml = `<button>BtnTest - ${this.btnIndex++}</button>`;
  element.innerHTML = element.innerHTML + this.buttonHtml;

  //after add button, get elment list by "querySelectorAll".
  let elementList = this.elRef.nativeElement.querySelectorAll('button');

  //Add event handler each.
  elementList[0].addEventListener('click', this.btnCellClick1.bind(this));
  elementList[1].addEventListener('click', this.btnCellClick2.bind(this));
}

btnCellClick1(){
     console.log('btn Click 1');
}

btnCellClick2(){
  console.log('btn Click 2');
}

Better way, preserves "this" context automatically:

this.elementRef.nativeElement.querySelector('.dynamic-anchor').addEventListener('click', () => {
  this.myComponentFunction();
});
Related