skip to Main Content

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

2

Answers


  1. You can use MutationObserver with childList: true to subscribe to specific DOM changes:

    const content = document.querySelector('#content');
    
    const observer = new MutationObserver((mutationsList, observer) => {
      console.log(`innerHTML updated, ${ mutationsList.length } mutation${ mutationsList.length > 1 ? 's' : '' }`);
    });
    
    observer.observe(content, { childList: true });
    
    for (let i = 0; i < 10; ++i){
       content.innerHTML += `<p>New element ${ i }</p>`;
    };
    
    setTimeout(() => {
      content.innerHTML += `<p>Added from setTimeout()</p>`;
    })
    
    setTimeout(() => {
      content.innerHTML += `<p>Added after 5 seconds</p>`;
    }, 5000)
    #content {
      padding-bottom: 67px;
    }
    
    #content > p {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100px;
      margin: 0;
      background: cyan;
      font-family: monospace;
      font-size: 32px;
    }
    
    #content > p + p {
      margin: 8px 0 0;
    }
    <div id="content">
      <p>0</p>
      <p>1</p>
      <p>2</p>
      <p>3</p>
      <p>4</p>
      <p>5</p>
      <p>6</p>
      <p>7</p>
      <p>8</p>
      <p>9</p>
    </div>

    Note, however, that your MutationObserver‘s callback won’t be invoked for every single statement that’s executed that updates .innerHTML (as they might cause a single paint, like the ones inside the for in the example above), but you can get the list of updated elements from mutationsList.

    However, if new elements are added at different points in time (like the one inside setTimeout), your callback will be invoked for each update.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search