10

This is the code that I'm using:

var ob = new IntersectionObserver(entries => {
    for(var entry of entries){
        console.log('works');
    }
});

document.querySelectorAll('dynamicElement').forEach(elem => ob.observe(elem));

This is working for elements that are on the page, but it doesn't work for elements that get dynamically created later. How do I bind an element that's inserted in the page later ?

I know with jquery you can bind it like $(document).on('event', 'element', 'func');, but how do I do it with the observer ?

Marcel
  • 123
  • 5

1 Answers1

1

Old question but basically I had the same problem recently and did not find any answer on the net so after investigating the obvious solution was to use the MutationObserver() API together with IntersectionObserver().

Basically you choose a non-dynamic parent of the dynamically generated children elements and attach a mutationObserver to its childList.

Subsequently on mutation detected (on the mutation observer callback) you select the dynamically generated element and attach the intersection observer to it.

Additionally if you use a querySelectorAll you can also use a forEach to attach an intersection observer to all the dynamic elements you wish as you were suggesting on your question.

Something like:

// Mutation Observer
   
const mSection = chatSection.querySelector(".non-dynamic-parent"),
    mObsOptions = {
      childList: true,
    },
    mObserver = new MutationObserver(mObs_CB);

  function mObs_CB(mutations) {
    for (let mutation of mutations) {
      if (mutation.type === "childList") {
        console.log("Mutation Detected");        

        //Start the Intersection Observer Here
        const intObsAllElem = document.querySelectorAll(".dynamicElement");        
        intObsAllElem.forEach(function (elem) {
          intObserver.observe(elem);
        });
      }
    }
  }

  mObserver.observe(mSection, mObsOptions);

 
//Intersection Observer
  
   const intObsOptions = {
         root: null,
         threshold: 1,
         rootMargin: "0px",
    },
    intObserver = new IntersectionObserver(intObs_CB, intObsOptions);

  function intObs_CB(entries, observer) {
      entries.forEach((entry) => {
         if (entry.isIntersecting) {
            console.log("intersecting");
         } else {
            console.log("not intersecting");
         }

      });

  }
electronixG
  • 136
  • 1
  • 1
  • 18
  • This is the same basic approach I use. I think what I've got may be a bit simpler, but anyway. Your code could do with some formatting, by the way :). Could garner an upvote from me, maybe after a little simplification of the structure and improvements in naming... – Darryl Noakes Jun 21 '23 at 23:26
  • 1
    Thanks, I am actually Electronics Engineer, not programmer, so this is the best I could come up with. For me it is like an achievement given that the answer was not found anywhere else and that I usually come to stack overflow for questions, not answers. – electronixG Jun 22 '23 at 01:46