Search code examples
javascripthtmldomcontainersaddeventlistener

Add EventListener in every change of an innerHTML in an div


Just for curiosity I want to get an event every time i add html code to a div like this

const xData = 40;

const container = document.querySelector('.container');

container.innerHTML = `<div class="container_Addons">${xData}</div>`;

container.addEventListener('i dont know',function(){
     console.log("you have just added some exotic stuff!");
});

for (i= 0; i<10;i++){
     container.innerHTML += `<div class="container_Addons">${i}st ${xData}</div>`;
};

to get an listener working every time i add html code


Solution

  • Using MutationObserver is quite easy to watch an element's childList change:

    // Utility functions:
    const el = (sel, par) => (par ||document).querySelector(sel);
    const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
    const repeat = (n, cb) => [...Array(n)].forEach((_, i) => cb(i));
    
    
    // Task: watch content changes:
    
    const xData = 40;
    const container = el('.container');
    
    const observeInsertion = new MutationObserver((records, observer) => {
      records.forEach(rec => {
        rec.addedNodes.forEach(node => {
          console.log(`Added some exotic stuff: ${node.textContent}`);
        })
      });
    });
    
    observeInsertion.observe(container, {
      childList: true
    });
    
    repeat(10, i => {
      const elAddon = elNew("div", {
        className: "container_Addons",
        textContent: `${i}st ${xData}`,
      });
      container.append(elAddon);
    });
    <div class="container"></div>

    The innerHTML constantly changes an element's full contents, therefore I opted for the much more suitable Element.append() method - in order to only be notified for that one specific child insertion. You can as well use .innerHTML = instead of .append(), but in such case you'll have to do extra useless and complicated work to detect what is exactly that was newly inserted.