Search code examples
javascripthtmlinnerhtmlwebapiintersection-observer

Infinite Scroll With Intersectionobserver & InnerHTML


I'm trying to make an infinite scroll (without jQuery) to show more results in a page. I'm using an IntersectionObserver to detect a div called #paginate and everytime it enters the screen, the #result div will be refreshed.

var result = document.querySelector('#result');
var paginate = document.querySelector('#paginate');

var observer = new IntersectionObserver(entries => {
if (entries.some(entry => entry.isIntersecting))
{
var pagination = 10;
fetch('/kernel/search.php?pagination='+pagination)
.then((response) => {
return response.text();
})
.then((html) => {
result.innerHTML = html;
});
}
});

observer.observe(paginate);

Here's the full code view with HTML:

<html>
<body>

<div class="row justify-content-sm-center justify-content-md-center justify-content-lg-center justify-content-xl-start no-gutters min-vw-100" id="result">
<div class="col-sm-11 col-md-11 col-lg-9-result col-xl-4-result order-0">

<div class="card mx-3 mt-3">
<div class="card-body">
<a class="text-decoration-none" href="?topic=result-1">
<h5 class="card-title"> 
Result 1    
</h5>
</a>
<p class="card-text text-truncate"> 
Result 1 description.</p>
</div>
</div>

<div class="card mx-3 mt-3">
<div class="card-body">
<a class="text-decoration-none" href="?topic=result-2">
<h5 class="card-title"> 
Result 2    
</h5>
</a>
<p class="card-text text-truncate"> 
Result 2 description.</p>
</div>
</div>

<div class="alert alert-light text-dark text-center border mx-3 my-3" id="paginate">
More results
</div>

</div>
</div>

<script>    
var result = document.querySelector('#result');
var paginate = document.querySelector('#paginate');

var observer = new IntersectionObserver(entries => {
if (entries.some(entry => entry.isIntersecting))
{
var pagination = 10;
fetch('/kernel/search.php?pagination='+pagination)
.then((response) => {
return response.text();
})
.then((html) => {
result.innerHTML = html;
});
}
});

observer.observe(paginate);
</script>

</body>
</html>

It works, but it only works the first time and it doesn't refresh the #result div thereafter. I can see the fetch working in Web Browser > Inspect > Network tab, but there's no activity after the first refresh of the #result div meaning it doesn't detect the #paginate div anymore.

What's going on here? I assume it's because that I'm using an innerHTML and the observer somehow can't detect the #paginate div after the first refresh of the #result div. How can I solve this?


Solution

  • I have removed innerHTML and replaced it with insertAdjacentHTML.

    Because innerHTML seems to reset/forget #paginate after the first refresh of the #result, so the observer can't detect #paginate anymore to trigger the next #result refresh.

    I could have used innerHTML with appendChild to do the same but appendChild adds a new div on each #result refresh, which I didn't really like.

    As the solution, I'm inserting the refreshed html data before the beginning of #paginate without resetting/forgetting it's element id that's required for the observer to trigger the next #result refresh.

    .then((html) => {
    paginate.insertAdjacentHTML('beforebegin', html);
    });