1

I am use a load more button in place of pagination. I just using jquery and ajax using this post as a starting point.

The problem I'm having is how to hide the button when there is no more posts to show. I thought I could do this with pagination but its not working out.

Here is my blog index:

            {% paginate craft.entries.section('blog').limit(2) as pageInfo, blogEntries %}

        <div id="post-output">

            {% for entry in blogEntries %}
                <article>
                    <h3><a href="{{ entry.url }}">{{ entry.title }}</a></h3>
                    <p>Posted on {{ entry.postDate.format('F d, Y') }}</p>
                    <p><a href="{{ entry.url }}">Continue reading</a></p>
                </article>
            {% endfor %}

        </div>

        {% if pageInfo.nextUrl %}

            <button id="more-button" data-page="{{craft.request.getPageNum()}}" data-batch="2">Load More</button>

        {% endif %}

Here is my javascript:

import $ from 'jquery';

$("#more-button").on('click', function () {
var btn = $(this),
    page = btn.data('page'),
    batch = btn.data('batch'),
    offset = page * batch,
    newPage = page + 1;

loadPosts(offset, batch);
// set the buttons page attribute to the new page it is on.
btn.data('page',newPage);

console.log('page');
console.log(newPage);
});

function loadPosts (offset, limit) {
$.get('/ajax/posts', { offset:offset, limit:limit }, function (data) {
    var postOutput = $('#post-output');
    postOutput.append(data);
});
}

and here is the ajax/_posts:

{% set offset = craft.app.request.getParam('offset') %}
{% set limit = craft.app.request.getParam('limit') %}
{% set moreitems = craft.entries.section('blog').limit(limit).offset(offset).all() %}

{% for entry in moreitems %}
<article>
    <h3><a href="{{ entry.url }}">{{ entry.title }}</a></h3>
    <p>Posted on {{ entry.postDate.format('F d, Y') }}</p>
    <p><a href="{{ entry.url }}">Continue reading</a></p>
</article>
{% endfor %}
  • I can't think of clean way to do this without PHP. You could eventually return a hidden input field with the remaining number of elements and check this input value with javascript after you appended the html but I'm not really a friend of avoiding PHP for certain reasons. The other way would be to check the lenght of data and hide the container if it's 0 – Robin Schambach Apr 18 '18 at 14:16
  • @RobinSchambach your comment gave me an idea. here is what I did in my blog index: {% set numOfpages = pageInfo.totalPages %} <button id="more-button" data-page="{{craft.app.request.pageNum()}}" data-batch="2" data-total="{{ numOfpages}}">Load More</button> – Danielle Frappier Apr 18 '18 at 16:43
  • and in the javascript: `$("#more-button").on('click', function () { var btn = $(this), page = btn.data('page'), batch = btn.data('batch'), total = btn.data('total'), offset = page * batch, newPage = page + 1; if ( newPage <= total ) { loadPosts(offset, batch); btn.data('page',newPage); } if ( newPage == total ) { $('#more-button').hide(); } }); – Danielle Frappier Apr 18 '18 at 16:45
  • 1
    @DanielleFrappier if that solution worked for you, would you mind adding that as an official answer? – Brad Bell Apr 18 '18 at 20:52
  • Sure no problem – Danielle Frappier Apr 19 '18 at 15:40
1

Here is what I did in my blog index:

        {% paginate craft.entries.section('blog').limit(1) as pageInfo, blogEntries %}

        <div id="post-output">

            {% for entry in blogEntries %}
                <article>
                    <h3><a href="{{ entry.url }}">{{ entry.title }}</a></h3>
                    <p>Posted on {{ entry.postDate.format('F d, Y') }}</p>
                    <p><a href="{{ entry.url }}">Continue reading</a></p>
                </article>
            {% endfor %}

        </div>

        {% set numOfpages = pageInfo.totalPages %}

        <button id="more-button" data-page="{{craft.app.request.pageNum()}}" data-batch="1" data-total="{{ numOfpages}}">Load More</button>

and in my javascript:

$("#more-button").on('click', function () {
var btn = $(this),
    page = btn.data('page'),
    batch = btn.data('batch'),
    total = btn.data('total'),
    offset = page * batch,
    newPage = page + 1;

console.log(newPage);
console.log(total);

if ( newPage <= total ) {

    loadPosts(offset, batch);
    // set the buttons page attribute to the new page it is on.
    btn.data('page',newPage);
}

if ( newPage == total ) {
    $('#more-button').hide();
}

});

function loadPosts (offset, limit) {
$.get('/ajax/posts', { offset:offset, limit:limit }, function (data) {
    var postOutput = $('#post-output');
    postOutput.append(data);
});
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.