Skip to content

Chapter 6 - Load more Past Events

It loads the next 6 past events each time the user clicks “Load more.”


  1. When the user clicks “Load more”:
    • A JavaScript handler is triggered.
    • A loading spinner is shown.
  2. The handler updates the pagination parameters:
    • start: first index of the next batch
    • end: last index of the next batch
  3. A new request is sent to Sanity:
    • Sanity returns the last 6 past events.
  4. The returned resources:
    • Are rendered through an internal endpoint (/api/v1/render-content-events/)
    • Are appended dynamically to the DOM
  5. When there are no more results:
    • The “Load more” button is hidden.

Inside the Past Events module we define:

  • The list container (js—past-events-list)
  • The “Load more” container (js—scroll-load-more)
  • The button (js—load-more)
flexible/modules/PastEvents.astro
<div class="f--container js--past-events-list">
...
<div class="js--results js--scroll-load-more"></div>
<div class="f--col-12 u--display-flex u--justify-content-center">
<button class="c--btn-a js--load-more">{translations.load_more_text.text}</button>
</div>
</div>

We define the GROQ query on the initial page load.
It fetches the first 6 past events, ordered by date in descending order (newest to oldest).

service/query/modules/past_events.js
_type == 'past_events' => {
...
'events': *[_type == 'events' && date < now()] | order(date desc)[0..5]{ //the first 6 past events
${resource({ language, isReference: false })}
},
'translations': *[_type == 'global_texts'][0]{
'load_more_text': *[_type == 'global_texts'][0]{'text' : past_events_load_more.${language} },
}
}

[0..5] = 6 items. Ordered by date descending.

DOM References and Initial Pagination State (hitsPerPage, start, end, language)

Section titled “DOM References and Initial Pagination State (hitsPerPage, start, end, language)”
scripts/handler/author/LoadMore.js
this.DOM = {
loadMoreContainer :document.querySelector(".js--load-more-container"),
loadMoreBtn : document.querySelector(".js--load-more-resources"),
authorID : document.querySelector(".js--author-id")?.value,
resultsContainer : document.querySelector(".js--results"),
}
// Settings
this.language = getCookie("preferred_lang") || "en"; // Default to English
this.hitsPerpage = 9; // Number of results per load
this.start = this.hitsPerpage;
this.end = this.hitsPerpage + this.start - 1;
this.contentPosition = "beforebegin"; // Default insert position for new HTML
this.emitter = payload.emitter;
scripts/handler/author/LoadMore.js
async loadMorePastEvents() {
try {
var query = `*[_type == 'events' && date < now()] | order(date desc)[${this.start}..${this.end}]{
'booth_number': booth,
'typeName': *[_type == 'post_type_names'][0]{'title' : events.${this.language} },
'is_external': boolean,
boolean => {
"external_url": external_link
},
'event_type': reference->title.${this.language},
"_type": _type,
"title": title.${this.language},
'location' : location.${this.language},
'date': date,
is_multiday => {end_date },
'event_type': reference->title.${this.language},
'total': count(*[_type == 'events' && date < now() ])
}`;
const { result } = await sanityClient.fetch(query, {}, {
filterResponse: false,
});
this.total = result && result.length > 0 ? result[0].total : 0;
const cards = result ?? [];
}
}

 Render the result and apply to the HTML/Astro

Section titled “ Render the result and apply to the HTML/Astro”
async loadMorePastEvents() {
...
let resultContent = "";
try {
const res = await fetch('/api/v1/render-content-events/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
data: cards,
language: this.language,
resultsTotal: this.total
})
});
const renderResult = await res.json();
resultContent = renderResult.result || '';
} catch(err) {
console.error("Error en fetch render-content:", err);
}
}

The “Load more” pattern on Events page works as follows:

  • Astro renders the first 6 events at build/load time.
  • JS handles incremental pagination via GROQ [start..end].
  • Cards are rendered through an internal API.
  • New items are appended to the DOM.
  • The “Load more” button disappears once all resources are loaded.

Algolia