I followed this tutorial here on how to paginate without reloading the page: http://craftsnippets.com/articles/dynamic-pagination-for-craft-cms
it uses Ajax to load in pagination without re-loading or exiting the page.
(it seems to be the most up to date tutorial I could find, but please correct me if I am wrong).
I have this working for one entry (a group of simple fields):
Before pagination:
After pagination:
So all is going well - the problem is when I need to show more than one of these on the page, I can get the pagination to load, but when I click the next ajax button (to load more content) - it either: Loads all the content together (loads the next page of all three) - or it loads the next page but updates all the content (the three lists) to have the same content.
Some examples:
Each list is added - with there own pagingation - but clicking next updates each list - not just the list that was clicked:
Image below shows that all paginated elements have moved to the next page instead of just the top one that was clicked on...
So - What I think is happening is that Ajax is being called for all elements and not just the speicic one that is being clicked on: cards on the table I have spent about 8 dev hours trying to figure this out and could really do with a keen eye that knows more about Ajax than me to point out the mistake:
Here is my code:
Index.twig
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="\ASSETS\CSS\main.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<header>
</header>
<body>
<section class="grid-col-3 container">
{% set tableData = entry.tableData.all() %}
{% for table in tableData %}
<div class="table">
<h3>{{table.alpha}}</h3>
<p>{{table.bravo}}</p>
<p>{{table.charlie|date('m/d/Y')}}</p>
</div>
{% endfor %}
</section>
{% include 'IMPORT/pagination/dynamic_pagination' with {
pagination_list: 'IMPORT/pagination/pagination_pages_list'
} %}
</body>
<!-- <footer>
</footer> -->
</body>
dynamic_pagination.twig
{# v2 #}
{% if pagination_list is defined %}
{% js %}
// AJAX REQUEST DATA
{% set current_url = craft.request.getRequestUri()|split(craft.request.getPath())[0]~craft.request.getPath() %}
{% set ajax_data = {
current_url: current_url,
pagination_list: pagination_list|hash,
pagination_parameters: pagination_parameters ?? null,
} %}
// JS SETTINGS
var loading_class = 'is-loading'
var pagination_list_class = 'js-pages-list'
var pagination_wrapper_class = 'js-pages-wrapper'
var animation_speed = 1000
// TWIG TO JS
var endpoint_url = '{{url(pagination_endpoint ?? 'pagination_endpoint')}}'
var url_params = '{{craft.app.request.getQueryStringWithoutPath() is not empty ? '?' ~ craft.app.request.getQueryStringWithoutPath()}}';
var current_url = '{{current_url}}'
var page_trigger = '{{craft.app.config.general.pageTrigger}}'
// AJAX REQUEST
var current_request = null;
function change_page(page_number, done){
current_request = $.ajax({
url: endpoint_url+'/'+page_trigger+page_number+url_params,
method: 'GET',
data: {{ajax_data|json_encode|raw}},
beforeSend: function(){
if(current_request != null) {
current_request.abort();
}
$('.'+pagination_list_class).addClass(loading_class);
var page = $("html, body");
page.on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function(){
page.stop();
});
page.animate({ scrollTop:
$('.'+pagination_wrapper_class).position().top }, animation_speed, function(){
page.off("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove");
});
}
}).always(function(){
$('.'+pagination_list_class).removeClass(loading_class);
}).done(function(data) {
$('.'+pagination_wrapper_class).html(data);
if(done){
done();
}
});
}
// BACK/FORWARD BUTTON
var initial_page = '{{craft.request.getPageNum()}}'
window.addEventListener('popstate', function(e) {
if(e.state){
change_page(e.state);
}else{
change_page(initial_page);
}
});
// PAGINATION CLICK EVENT
$('.'+pagination_wrapper_class).on('click', '[data-number]', function(e){
e.preventDefault();
var selected_page = $(this).attr('data-number');
change_page(selected_page, function(){
history.pushState(selected_page, null, current_url+'/'+page_trigger+selected_page+url_params);
});
});
{% endjs %}
<div class="js-pages-wrapper container">
{% include pagination_list with {
pagination_parameters: pagination_parameters ?? null,
} %}
</div>
{% endif %}
pagination_pages_list.twig
{# v1 #}
{# example element query - adjust it to your website #}
{% set tableData = craft.entries.section('home').one().tableData %}
{% set tableData2 = craft.entries.section('home').one().tableData2 %}
{% set tableData3 = craft.entries.section('home').one().tableData3 %}
{% paginate tableData.limit(3) as pageInfo, pageEntries %}
{% paginate tableData2.limit(3) as pageInfo2, pageEntries2 %}
{% paginate tableData3.limit(3) as pageInfo3, pageEntries3 %}
{% if craft.request.isAjax() %}
{% do pageInfo.setBasePath(craft.request.getParam('current_url')) %}
{% endif %}
{# replace code below with your entries list and pagination component #}
{% include 'IMPORT/components/pagination' %}
<br>
<div class="js-pages-list grid-col-3">
{% for entry in pageEntries %}
<div class="entryItem">
<h3>{{entry.alpha}}</h3>
<p>{{entry.bravo}}</p>
<p>{{entry.charlie|date('d,m,Y')}}</p>
</div>
{% endfor %}
</div>
{% include 'IMPORT/components/pagination2' %}
<br>
<div class="js-pages-list grid-col-3">
{% for entry in pageEntries2 %}
<div class="entryItem">
<h3>{{entry.alpha}}</h3>
<p>{{entry.bravo}}</p>
<p>{{entry.charlie|date('d,m,Y')}}</p>
</div>
{% endfor %}
</div>
{% include 'IMPORT/components/pagination3' %}
<br>
<div class="js-pages-list grid-col-3">
{% for entry in pageEntries3 %}
<div class="entryItem">
<h3>{{entry.alpha}}</h3>
<p>{{entry.bravo}}</p>
<p>{{entry.charlie|date('d,m,Y')}}</p>
</div>
{% endfor %}
</div>
pagination.twig <<<
I have duplicated this file for each of the lists and changed the just changed the pageInfo to either pageInfo2 or pageInfo3
{# requires pageInfo variable #}
{# settings #}
{% set neighbours = 1 %}
{# symbols #}
{% set prev = '❮' %}
{% set next = '❯' %}
{% set dots = "…" %}
{# single numeric link #}
{% macro numericLink(url, number, current) %}
<li>
<a href="{{url}}" data-number="{{number}}" class="pagination-link {{current ? 'is-current' : null}}" aria-label="{{current ? 'current page'|t : 'go to page'|t ~ ' ' ~ number}}" {{current ? 'aria-current="page"'}}>{{number}}</a>
</li>
{% endmacro %}
{# next/prev link #}
{% macro textLink(url, content, aria, number) %}
<li>
<a href="{{url}}" data-number="{{number}}" class="pagination-link" aria-label="{{aria}}">{{content|raw}}</a>
</li>
{% endmacro %}
{# ellipsis #}
{% macro ellipsis(content) %}
<li>
<span class="pagination-ellipsis">{{content|raw}}</span>
</li>
{% endmacro %}
{# pagination logic #}
{% if pageInfo is defined and pageInfo.totalPages > 1 %}
{% import _self as self %}
{# seomatic #}
{# https://github.com/nystudio107/craft-seomatic#pagination-and-seo #}
{% if seomatic is defined %}
{% do seomatic.helper.paginate(pageInfo) %}
{% endif %}
<nav class="pagination" role="navigation" aria-label="{{'pagination'|t}}">
<ul class="pagination-list">
{# previous #}
{% if pageInfo.prevUrl %}
{{ self.textLink(pageInfo.prevUrl, prev, 'previous page'|t, pageInfo.currentPage - 1) }}
{% endif %}
{# first #}
{% if pageInfo.currentPage - neighbours > 1 %}
{{ self.numericLink(pageInfo.firstUrl, '1') }}
{% endif %}
{# ellipsis before current #}
{% if pageInfo.currentPage - neighbours > 6 %}
{{ self.ellipsis(dots) }}
{% endif %}
{# links before current #}
{% for page, url in pageInfo.getPrevUrls(neighbours) %}
{{ self.numericLink(url, page) }}
{% endfor %}
{# current #}
{{ self.numericLink('', pageInfo.currentPage, true) }}
{# links after current #}
{% for page, url in pageInfo.getNextUrls(neighbours) %}
{{ self.numericLink(url, page) }}
{% endfor %}
{# ellipsis after current #}
{% if pageInfo.totalPages - pageInfo.currentPage > neighbours + 1 %}
{{ self.ellipsis(dots) }}
{% endif %}
{# last #}
{% if pageInfo.currentPage + neighbours < pageInfo.totalPages %}
{{ self.numericLink(pageInfo.lastUrl, pageInfo.totalPages) }}
{% endif %}
{# next #}
{% if pageInfo.nextUrl %}
{{ self.textLink(pageInfo.nextUrl, next, 'next page'|t, pageInfo.currentPage + 1) }}
{% endif %}
</ul>
</nav>
{% endif %}
You can find the full git gist of these files on this link (from the tutorial not my modifed version)
https://gist.github.com/piotrpog/6c8d76a882fef8c82ea8eda99317bf1d
--
I know this is pretty hacky - so if there is any other way that you would do this to make it simpler then please let me know and I would happy to go that route.
Thanks in advance - W