Load More
The LoadMore class
The LoadMore class is a JavaScript class we use to dynamically load content on a web page, supporting pagination, taxonomy filtering, and search functionality. This class interacts with various DOM elements like load more buttons, taxonomy filters, search bars, and displays the content in a specific container. Through user events (such as clicks and filter changes), it makes AJAX requests to an endpoint on the server to fetch the necessary data and update the view without reloading the page.
Implementation
Let’s go over an example of a Load More feature to load insights, where we have two filters (taxonomy and ACF), a Load More button, and a Search Bar to dynamically fetch and display posts.
The data flow begins when the LoadMore class makes an AJAX request to an endpoint on the server, typically defined in WordPress through wp_ajax or wp_ajax_nopriv as Custom Endpoint to work with Ajax (seen previously). This endpoint receives a series of parameters, like the post type, posts per page, search term, and filtered taxonomies. The server processes these parameters and returns the corresponding HTML, which is then injected into the page, updating the content without reloading it.
add_action('wp_ajax_load_insights', 'load_insights_callback');add_action('wp_ajax_nopriv_load_insights', 'load_insights_callback');
function load_insights_callback() { $args = array( 'post_type' => 'insight', 'posts_per_page' => $_POST['posts_per_page'], 'offset' => $_POST['offset'], // Other query parameters like search term, taxonomies, etc. ); $query = new WP_Query($args); $posts = $query->posts;
// Generate HTML for the posts $html = ''; foreach ($posts as $post) { $html .= '<div class="post">' . $post->post_title . '</div>'; }
echo json_encode(['html' => $html, 'postsTotal' => $query->found_posts]); die();}
Obviously, the HTML file contains the main structure of the page. It includes the container where the posts will be displayed (resultsContainer), the taxonomy filters, the search bar, and the “Load More” button. It also loads the necessary JS files (LoadMore.js and main.js).
LoadMore.js: This file contains the LoadInsights class that manages the functionalities of loading more content, search, and taxonomy filtering. The class listens for events like clicks on the “Load More” button, changes in filters, or keyups in the search bar, and calls the WordPress endpoint to fetch more results. We don’t usually change the code in this file unless it’s needed or custom actions need to be added.
In our Main.js file, we initialize the LoadMore class with the necessary parameters (query, DOM elements, etc.). Here we also handle global events like initializing the filters and search bar.
if (document.querySelectorAll(".js--section-container").length) { const loadMoreButton = document.querySelector(".js--load-more-posts"); const featuredInsightElement = document.querySelector(".js--featured-insight"); const page_id = featuredInsightElement && featuredInsightElement.dataset.pageId;
const insightsLoadMore = { dom: { resultsContainer: document.querySelector(".js--results-container"), searchBar: document.querySelector(".js--posts-search"), typesFilter: document.querySelectorAll(".js--insight-types-dropdown"), capabilityFilter: document.querySelectorAll(".js--insight-capability-dropdown"), topicsFilter: document.querySelectorAll(".js--topics-dropdown"), triggerElement: loadMoreButton, noResultsElement: document.querySelector(".js--no-results-message"), resultsNumber: document.querySelector('.js--results-number'), loader: document.querySelector('.js--loading'), spinner: document.querySelector('.js--spinner-load-more') }, query: { postType: loadMoreButton && loadMoreButton.dataset.postType, postPerPage: parseInt(loadMoreButton && loadMoreButton.dataset.postsPerPage), offset: parseInt(loadMoreButton && loadMoreButton.dataset.offset), total: parseInt(loadMoreButton && loadMoreButton.dataset.postsTotal), page_id: page_id, taxonomies: [], action: "load_insights", }, isPagination: false, callback: { onStart: () => { }, onComplete: () => { }, }, }; document.querySelectorAll(".js--section-container").forEach((element, index) => { this.boostify.observer({ options: { root: null, rootMargin: "0px", threshold: 0, }, element: element, callback: async () => { this.instances["LoadInsights"] = []; await import("@jsModules/loadMore/LoadInsights").then(({ default: LoadInsights }) => { window["lib"]["LoadInsights"] = LoadInsights; });
this.instances["LoadInsights"][index] = new window["lib"]["LoadInsights"](insightsLoadMore); }, }); }); }
Variants
- Load More: When the “Load More” button is clicked, the query is updated to show more posts. The server processes the offset and postsPerPage values and returns additional results to append to the container.
handleLoadMore() { const newOffset = this.payload.query.offset + this.payload.query.postPerPage; this.payload.query.offset = newOffset; this.loadMore(false);}
- Search Bar: The search bar allows the user to filter posts by text. As the user types, the search term is updated, and a new AJAX request is made to fetch the relevant posts.
handleSearchBarKeyup() { this.payload.query.searchTerm = this.payload.dom.searchBar.value; this.loadMore(true);}
- Taxonomy Filter: Taxonomy filters let users select specific terms to filter posts by. When a filter is changed, the taxonomies array is updated and the query is re-sent to the server.
handleFilterChange(event) { const filter = event.target; this.payload.query.taxonomies.push({ [filter.dataset.type]: filter.value }); this.loadMore(true);}
- ACF Filter: Similar to taxonomy filters, ACF filters allow additional filtering based on custom fields. The selected values are added to the query, and the server adjusts the WP_Query accordingly.
handleACFFilterChange(event) { const filter = event.target; this.payload.query.acfFilters.push({ field: filter.dataset.field, value: filter.value }); this.loadMore(true);}