4

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.

5
  • basically map gets ready. All addresses are geolocated on map. But the popup that comes on hover is added dynamically to the dom whenever user hover over any pin. My link is inside that popup. Commented Jan 10, 2019 at 13:32
  • sorry, I don't have live link right now. Are you adding dynamic html as a string? or to the document object? How are you assigning the event? Commented Jan 10, 2019 at 13:46
  • I create a HTML element and after info.onclick = function(){}. For instance info is my HTML element. Once Map is ready, the info exist but does not display, and binding event works. Commented Jan 10, 2019 at 13:54
  • Would be helpful if you let me know how you create info. Commented Jan 10, 2019 at 13:57
  • 'var info = new MQA.Poi({ lat: 39.743943, lng: -105.020089 });' Like this. This is a plugin method. Commented Jan 10, 2019 at 13:58

3 Answers 3

11

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

Sign up to request clarification or add additional context in comments.

9 Comments

I tried this. instead of button I used class name of the anchor link. It did not fire the event.
One thing here is my links will not be on DOM during ngAfterViewInit event processing. The link is added dynamically by plugin when user hover over the address pin.
@Jay Button is the element name not class.... also you can put that piece of code into a method and call after whenever the element is created.
Element is created dynamically by plugin. The configuration of the plugin accepts the html string data that would be displayed when certain event happens.
yes, I am passing the string. to the plugin. Plugin creates the hover popup.
|
1

Better way, preserves "this" context automatically:

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

Comments

0

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');
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.