Back to all articles
Load more posts with ajax in wordpress, without page reload.
Development

Load more posts with ajax in wordpress, without page reload.

Updated on November 9, 2023

Looking for a new website?

Get in touch
Save your eyes, enable dark-mode!

Loading more posts with ajax is a very popular UI button in today’s websites. On WordPress, a lot of people use plugins, page builders, or free/purchased themes that come shipped with this functionality. But writing it custom is not that hard either! So let’s try to create one today. As a bonus, we also cover load-more with pagination and the horror of the WordPress ‘offset’ function when trying to paginate.

load more posts ajax

I’ve covered this topic a few years ago when I was young and inexperienced. When I look back an the way I loaded more posts with ajax back then, I get the feeling every programmer has looking back at his/her code from a few years back. But… the post received a decent amount of traffic so I kept it online to help people create their own ajax load more function. But if you want a laugh, please visit my older way of loading more posts on WordPress with ajax 🙂

Now, a few years later, the time has passed and I use the admin-ajax function from WordPress way more instead of creating my own API calls to receive my posts. So this is what I’ll cover in this post:

The WordPress query to load posts from a (custom) post type

Let’s start off with the basic query for our posts. The query will display the first 6 posts from our post-type ‘publications’. As you can see, I also added the ‘paged’ parameter but hardcoded it to 1. This is because we’ll be loading more posts using javascript and are not listening to a query parameter. Visiting website.com/page/2 will NOT display the second page in this example as we’re not listening to the query var.

The following code example should go in your template file where you want to display your post-list. I’m using get but you can hardcode your card template in this loop as well. Having them as a template part makes it clearer later when we’re also loading those cards using javascript.

<?php 
$publications = new WP_Query([
  'post_type' => 'publications',
  'posts_per_page' => 6,
  'orderby' => 'date',
  'order' => 'DESC',
  'paged' => 1,
]);
?>

<?php if($publications->have_posts()): ?>
  <ul class="publication-list">
    <?php 
      while ($publications->have_posts()): $publications->the_post();
        get_template_part('parts/card', 'publication');
      endwhile;
    ?>
  </ul>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

<div class="btn__wrapper">
  <a href="#!" class="btn btn__primary" id="load-more">Load more</a>
</div>

The code above can be split into 3 main sections. The first one is the query to actually get the first 6 posts from ‘publications’. The second part is our loop over the results of the $publications query. Don’t forget to call the wp_reset_postdata() function, in the end, to make sure the rest of our page continues to work correctly. Finally, we also add the “load more” button under our list to be able to load more posts.

Now that we have our base setup ready, it’s time to link some javascript and Ajax to that load-more button!

The load more ajax function

Now it’s time to add a click event to our load more button. I will be using jQuery in this tutorial, as it comes shipped by default with WordPress. And because this post is specifically for loading more posts with Ajax in WordPress, I will be doing just that.

For the JS part, head over to your javascript folder and add a click event to the button. You can use arrow functions if you’re feeling fancy, but because I did not cover a babel-compiler setup I’m going for the more stable old-school way:

$('#load-more').on('click', function() {
  // We will do our magic here soon!
}

Before we continue, there are a few things we need to keep in mind. We want to load ‘more posts’, not just any posts, but more specifically only the next page of posts. So we need to keep track of the current page we’re on, and the page we want to load next.

The benefit of using Ajax to load more posts is that our page will not refresh. This means that we can remember things in plain javascript, without the need of storing data in localStorage or using some sort of $store as we have in React or Vue. A simple variable in javascript will do just fine.

We will edit our javascript snippet with a variable to keep track of the current page, and we add the $ajax call to our ajax function that we will write in the next chapter.

let currentPage = 1;
$('#load-more').on('click', function() {
  currentPage++; // Do currentPage + 1, because we want to load the next page

  $.ajax({
    type: 'POST',
    url: '/wp-admin/admin-ajax.php',
    dataType: 'html',
    data: {
      action: 'weichie_load_more',
      paged: currentPage,
    },
    success: function (res) {
      $('.publication-list').append(res);
    }
  });
});

If you want to test this snippet to make sure it’s working I need to disappoint you. This will not work just yet. We are now making a call to a WordPress function that we did not write yet! So let’s do that first before testing or complaining that it is not working.

But we can still test it to make sure we’re going in the right direction so far. When you click the load more button, nothing should happen visually on the page. But if you open your chrome dev tools and navigate to the Network tab, you should be able to see that we made an ajax request to admin-ajax.php.

This admin-ajax.php request will only become visible when you click our button. Clicking it again will make a second call (and then our payload should show ‘paged: 3’). We can see two things in our payload: The ‘action’ and ‘paged’. These are the two things we passed in our javascript $ajax call under data {}. It should return an error for you, as it cannot find our function ‘weichie_load_more’.

The payload is what we’re sending from our frontend to our backend. Because of this payload, we have access to the page we want to load in our PHP function where we will be doing the query. So next up: Creating our weichie_load_more function that will actually load more posts for us.

I don’t know how familiar you are with WordPress Queries and custom plugins? Some developers prefer creating plugins for their custom code, but I prefer to add our functionalities straight into the functions.php file in our WordPress root.

You may add the following snippet to your functions.php:

function weichie_load_more() {
  $ajaxposts = new WP_Query([
    'post_type' => 'publications',
    'posts_per_page' => 6,
    'orderby' => 'date',
    'order' => 'DESC',
    'paged' => $_POST['paged'],
  ]);

  $response = '';

  if($ajaxposts->have_posts()) {
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
      $response .= get_template_part('parts/card', 'publication');
    endwhile;
  } else {
    $response = '';
  }

  echo $response;
  exit;
}
add_action('wp_ajax_weichie_load_more', 'weichie_load_more');
add_action('wp_ajax_nopriv_weichie_load_more', 'weichie_load_more');

As you can see, our query part is actually the exact same thing as we have in our page template. We’re performing the exact same query, but the only difference here is that we’re pulling paged: 2 (or 3 or 4) instead of the first page.

We have our $ajaxposts which is our WordPress query we’ll be looping over (exactly like we do in our page template). We also declare a variable $response that will store our results. We then loop over our ajaxposts and in each iteration, we append our template_part to our response using the .= notation. And finally, we echo our $response and this is what we’ll be sending back to our javascript.

This is because of the pagination. We don’t want to pull the same posts when clicking on ‘load more’, but give us the same amount of posts, from the next page. Now that we have this, we can test if clicking on the button still returns an error or not. But normally, it should return us the HTML blocks of the 6 posts from page 2. You can check this out in our network tab again, but instead of going to Payload (what we’re sending to the backend) we can check under Response (what the backend is sending back to the frontend)

Combining load more with Ajax and WordPress

Cool, now that we have a response that is sending back our new list items for page 2, it’s time to make them appear on the website. The ‘Response’ we’re seeing in our network tab is automatically returned to our $ajax request.

If you’re lucky, our current code could be already working for you. When you take a look at our current JS part, we already have a success: function in our ajax call:

// Nothing changed in our JS. This is just to show which part I'm talking about.
$.ajax({
  ...
  dataType: 'html',
  ...
  success: function (res) {
    $('.publication-list').append(res);
  }
});

The success function takes a parameter ‘res’ that holds our ajax response. Because we passed a dataType in our call, it knows we’re expecting HTML for the response. We simply target our $(‘.publication-list’) and .append the result (which is HTML). The append function is default jQuery.

Debugging: If the code is not working for you, we need to debug a little more. Try to log your res to the console and check what type of data is returning for you. You can’t write any js inside our ajax object, but because the success: function() { ... } – obviously – is a function, we can write console.log(res)inside the success function for debugging.

Now that our code is working and actually loads more posts, you’ll probably discover another problem soon, if the programmer in you hasn’t already. What if there are no more posts? Example: We have 4 pages and we reached page 4, then clicking on our load more button will load page 5 -> which is empty. We need to hide our load more button when we reached the last page, or add an inactive class or whatever you would like to do at the end.

They also check if we’re on the last page, we will change our ajax call to not return plain HTML, but to actually receive a JSON response. In this response, we will both put our HTML response (as we already have it right now) and the max_pages. This is needed to check if our current page index is bigger or equal to the max_pages. If so, we can hide our button because we reached the max amount of pages.

First things first, update our ajax call to work with JSON instead of HTML. Please note that making this change will break our current functionality for now, but we will fix it shortly!

In your JS file, change the ajax call to the following:

$.ajax({
  type: 'POST',
  url: '/wp-admin/admin-ajax.php',
  dataType: 'json', // <-- Change dataType from 'html' to 'json'
  data: {
    action: 'weichie_load_more',
    paged,
  },
  success: function (res) {
    $('.publication-list').append(res);
  }
});

We only changed the dataType for now. We also need to change our response in a minute, but first, we’ll be updating our PHP Query in the functions.php file to the following:

function weichie_load_more() {
  $ajaxposts = new WP_Query([
    'post_type' => 'publications',
    'posts_per_page' => 6,
    'orderby' => 'date',
    'order' => 'DESC',
    'paged' => $_POST['paged'],
  ]);

  $response = '';
  $max_pages = $ajaxposts->max_num_pages;

  if($ajaxposts->have_posts()) {
    ob_start();
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
        $response .= get_template_part('parts/card', 'publication');
    endwhile;
    $output = ob_get_contents();
    ob_end_clean();
  } else {
    $response = '';
  }

  $result = [
    'max' => $max_pages,
    'html' => $output,
  ];

  echo json_encode($result);
  exit;
}
add_action('wp_ajax_weichie_load_more', 'weichie_load_more');
add_action('wp_ajax_nopriv_weichie_load_more', 'weichie_load_more');

We changed a few more things in our PHP query than we had in our JS. But let’s go over them in more detail. The query itself remains untouched. We also still have our empty string $response = '';. We then use a default WordPress functionality to catch the max_num_pages from a query. This will return the maximum amount of pages we have for this query. So our load more button can max load “max_num_pages”-amount of pages.

Then while we’re looping over our query and appending each found post to our $results string, we actually wrap it this time inside a PHP buffer, called output buffer. While output buffering is active, no output is sent from the script and the output is stored in an internal buffer instead. before we end our output buffer, we store the result in another variable named $output.

In the end, right before we will return our results back to our javascript file, let’s create our return array:

// Nothing changed, just zooming in on our final result array
$result = [
  'max' => $max_pages,
  'html' => $output,
];
echo json_encode($result);

We create an array that takes the $max_pages, to return the max amount of pages for this query, and our HTML. The $output we’ve created from within our post-loop. To return an array back to our json file, we need to encode the array for JSON and return it like that.

Finally, to work with our new output, we also need to tweak our javascript. Because we’re not getting HTML as a response, but JSON, we need to go one level deeper when printing the response to the page. Change your javascript success function to the following:

$.ajax({
  ...
  success: function (res) {
    if(paged >= res.max) {
      $('#load-more').hide();
    }
    $('.publication-list').append(res.html);
  }
});

Our ‘res’ from our function(res) will now hold a json object with 2 key-value pairs. A key ‘max’ that holds our max_num_pages and a key ‘html’ which holds the HTML of our response.

To display our HTML list again on our page, we’ll need to use res.html. We also check if pages >= res.max to see if we need to hide our button, or if we did not reach the maximum amount of pages yet.

Using WordPress pagination with Offset

Using ajax in WordPress to load more posts or to filter posts in WordPress, it’s all fun and games as long as it actually works! If you can’t get it to work, there is no fun in making those things custom. And I had this when I tried to use this load-more script we just wrote, together with an offset.

The WordPress pagination simply does not work when you use an offset. The pagination query is completely broken and I don’t know why. But the entire script above is ready for the trash. I Googled around and there is literally no solution to make pagination work together with an offset.

How I ended up fixing this, is to create the offset myself as well… So in this example, I am skipping the 3 most recent posts, and want to paginate after that. To paginate the query without the latest 3 posts. Normally, I can simply use offset: 3 but with pagination, no way josé!

This is what I ended up doing instead:

$recent_publications = new WP_Query([
  'post_type' => 'publications',
  'posts_per_page' => 3,
  'orderby' => 'date',
  'order' => 'DESC',
  'fields' => 'ids',
]);

$ajaxposts = new WP_Query([
  'post_type' => 'publications',
  'posts_per_page' => 6,
  'orderby' => 'date',
  'order' => 'DESC',
  'paged' => $_POST['paged'],
  'post__not_in' => $recent_publications->get_posts()
]);

I first create a query that pulls the most recent 3 posts. Afterward, I create our actual WP Query, and instead of using offset, I exclude the posts from our first query. In other words: Skip the most recent 3 posts, in the query where we want to use pagination. It’s the same as offset, but with additional steps.

If you found an easier solution to make pagination work with offset, please leave your solution in the comments!

Common mistakes with an ajax query in WordPress

The pagination or page count is not correct

If the pagination or the amount of posts returning from the query is not correct, try adding 'post_status' => 'publish' to your query. It might be that WordPress messes up the count because it’s also counting private or draft posts. Those are included in the count of the query but are not printed on the page.

Conclusion

I hope my article was clear and helpful for you to create your own ajax load more button. You can play with this to update our code that instead of clicking on the load more button, you will trigger our load-more function when we reach the bottom of the page. This is a way to create a simple infinite-scroll without any plugins.

Make sure to also check my other post on how to filter posts with ajax in WordPress. It’s using the same login as in this post. It can also help if you’re trying to make ajax filters together with ajax load more.

Leave a Reply

Your email address will not be published. Required fields are marked *

54 Comments

  • hasintha says:

    Thanks sire, much obliged

  • alessio says:

    Great tutorial! Would it require a lot of adaptation to extend this use case to a paginated list as follows

    << >>

    Thansk in advance for any help,

    Alessio

  • Alex says:

    This is great, and I’ve got it all working – thank you for the easy to follow walkthrough!

    One issue that I’m facing however is that the returned posts via Ajax are ignoring my custom excerpt length for posts:

    function new_excerpt_length($length) {
    return 20;
    }
    add_filter(‘excerpt_length’, ‘new_excerpt_length’);

    The ajax loaded posts – for some reason – are returning with exactly 100 words.

    Any ideas?

    • Oscar Obians says:

      Hi Nikita, Hi Bob,
      First thank you for this amazing tutorial. Also thank you so much Nikita for sharing your snippets to help combine the Ajax Filtering with the Load More Button. It was just what I needed. I’ve attempted to implement this on a website I’m building and I’m stumped right now. I’ve got it to work without any errors as far as I can tell. The only problem is that it just returns a blank response and the space where the new paginated posts should appear also becomes blank. For Context, I’m using Bricks Builder for the frontend and I’ve added the necessary data attributes at the front end. Problem as I suspect is in the process of converting the JSON to HTML but I might be wrong.

  • Narimane says:

    Un grand merci pour vous Monsieur, vous m’avez vraiment aidé avec ce tuto!
    je vous demande s’ils vous plait si vous avez d’ autres tuto pour les filtres et le tri de select option qui doivent être faits en appelant l’API de WordPress avec Ajax, je suis vraiment perdu sur ce point!
    je vous souhaite une bonne continuations!

  • MD Ariful islam says:

    On the chrome dev tools I am unable to make requests to admin-ajax.php . I am getting 404 error. Please suggest me how can is solve it.

    • Bob Weichler says:

      The 404 means that you are sending a request to a file that does not exist. Make sure the path to your admin-ajax.php is correct and that the function name exists. Otherwise I’ll need a screenshot or something to be able to help out.

  • Faisal says:

    Thank you so much

  • mohammad says:

    dear Mr,
    thank you a lot for your time to write this perfect solution code. I indeed used it in my project.
    God bless you, and wish you success additionally of your current success

  • Cornelia says:

    Hi,
    thank you so much for this walkthrough! But I can’t get the script to work, and get the error: “Uncaught ReferenceError: currentPage is not defined”.

    If I delete the parts using currentPage (I can’t see it in your final code snippets) I instead get the error:
    “Uncaught ReferenceError: paged is not defined”

    Do you have any clues why?

    • Bob Weichler says:

      Hi Cornelia, Thank you for your response! There is indeed a bug here in my post where I forgot the part that you need to make ‘paged’ working. Please find my answer here in the comments on a reply from Hans. There I explain where the paged is comming from. The comment itself is from 11/05/2022. Hope it helps!

  • Cornelia Börjesson says:

    Hi!
    So I’m trying to implement the load more function together with the filtering on a start page with no luck. The categories listed in the filtering are the ones for the regular post type, and when I’m adding: ‘team-location’,
    ‘hide_empty’ => true,
    ‘orderby’ => ‘name’,
    ‘order’ => ‘DESC’,
    )
    );
    foreach ($terms as $term) { ?> the filter links are correct but the functionality fails.

    How do I implement these two functions to the start page?

    Many thanks in advance!

  • Toancr says:

    thank u ad

  • Elyes Z says:

    Hi orjan,
    The same for me, How you resolved this problem please ?

  • John Ryder says:

    Thank you for sharing this information, very helpful. I have been learning WordPress theme development for the last two years and now I’m on to Ajax!

  • Stefan Repac says:

    Wow, thank you for code breakdown, and offset example.

  • Fachu says:

    Sorry, one comment: In the console, inside Network, I can see the event and the correct Response, but is not showing in the html. Thank you.

  • Fachu says:

    Hey Weichie! Thank you for this tutorial, it’s so clear, really.

    I have a question, I’ve a problem with the button in Mobile. I cannot click at browser and touch it at phone. I tried with ” $(‘#load-more’).on(‘click touchStart’, function() ” but still happening.

    Any idea?

    Thank you again.

  • Mmp says:

    Hi! It is so helpfull. Thank you.
    Everything is very clear, however, maybe someone have some troubles with the JSON result. To avoid eventual troubles, just make a parse for the result, like:

    success: function (res) {
    result = JSON.parse(res);
    if(currentPage >= result.max) {
    $('#ajax-load-more').hide();
    }
    $('.mosaiko-load-more-container').append(result.html);
    }

  • mina says:

    Hi I use codes in this article but it does’nt work . json_encode($result) doesnt show anything

    • Bob Weichler says:

      Hi Mina, could you send me a little bit more info about your code using pastebin or codepen? If json_encode($result) does not show anything, something else is going wrong before this code.

  • Ottodix says:

    For adding a custom offset, did you try this solution provided by the documentation, using pre_get_posts hook?
    https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination

    • Bob Weichler says:

      Hi Ottodix, Thank you for your comment. I do not remember if I tried that option in my ajax queries, but it does indeed look like a valid solution! I’ll re-investigate next time I need it and will update my post accordingly. Thanks!

  • Luan says:

    Hey thanks this was really helpful, what do you think would be correct way to add a little spinner animation while the server loads its response? As in the JS logic behind it

    • Bob Weichler says:

      Hi Luan,

      Thank you for your question. You can add the spinner on your page and hide it using css. In your JS you can add a show/hide class to the spinner, or hide/show it using jQuery. Here a quick snippet below:

      $('.button').on('click',function()){
        $('.spinner').show();
      
        $.ajax({
          ...
          success: function (res) {
            $('.spinner').hide();
            ...
          }
        });
      }

      Hope it helps!

  • Nikita says:

    Hi Bob!
    Thank you for your blog. It very helpful!
    I’m also try to merge load more and filtering.
    But nothing in comments helps me.
    I take a load more code.

    *** code removed ***

    When I press category filter it display right post. But when i press load more it display second post from all category, not from category I chose. I can’t understand how to fix it.

    • Bob Weichler says:

      Hi Nikita,
      Thank you for your comment. Please wrap your code or use Gist or pastebin to share your code. I removed your code from your response as it was not readable and bloated the comment section, sorry. Feel free to paste it again (using gist/pastebin) and I’ll have a quick look with you.

      • Nikita says:

        Hi Bob,
        Sorry for not readable code.
        Now I’m upload it to pastebin.
        Here code with ajax (filtering and load more) – https://pastebin.com/pVFTYtfS
        And this for functions.php – https://pastebin.com/UAVSwLBy

        • Bob Weichler says:

          Thank you for sending it in this format. Do you also have a data-slug on your load-more buttons in your html? I see you’re using two times category: $(this).data('slug') in your javascript functions. But those are two different buttons. Does the load-more button also has the current category as a data attribute?

          • Nikita says:

            Ohh, I forgot to add category data. But I added it now.
            And now I have other problems.
            1. Load more button now displays max 4 posts when I’m loading posts from all categories (there should be 9). Load more button hides after 4 post are displayed.
            2. When I apply a filter (any filter) the same exact posts are displayed is each filter.

            Link to html file – https://pastebin.com/wCtNdKAp

          • Bob Weichler says:

            Hi Nikita,
            I can only advise you to keep checking your network tab in the browser to see if you’re actually sending the correct data from Ajax to your PHP script and to check if you are receiving the preferred data back in the PHP response. You can also try your functions.php query first without dynamic data (just hardcore category in the code) and see if that gives you everything correctly. And continue from there.

          • Nikita says:

            Hi Bob,
            Thank you!
            I try check all sending data. When all will be work I share my code here.

          • Nikita says:

            Hi Bob!
            Finally I merge “Load more” and “Filtering”.
            I’m attach links to code. I hope someone find it useful.

            AJAX query file – https://pastebin.com/ckG0K707
            Page with posts – https://pastebin.com/Ej9eb3d1
            Functions file – https://pastebin.com/imDiqnqW

  • Ohad says:

    everything written before the title “Hide load more button when no more post” works fine.
    but what you write after this title throw an error “paged not defined”, from the ajax call on data object.

    so after I click the button I get this error on console.
    “Uncaught ReferenceError: paged is not defined”

    • ohad says:

      actually I just saw your reply on one of your comments and it works. thanks a lot you did a great post!

  • Federico says:

    This tutorial is just what i looking for.
    However, when i click the “Load more” button, i get an error from http://mysite.local/wp-admin/admin-ajax.php 400 (Bad Request)

    • Federico says:

      Nevermind, i had a typo in the add_action part that caused the error 400.
      Thanks for this great piece of code.

    • Brandon says:

      This is what I did to fix this:

      Set in your ajax function set the following:
      data: {
      action: ‘weichie_load_more’,
      paged: currentPage,
      },

      Then in within you ajax function, set the success function if statement to this:
      if(currentPage >= res.max) {
      // hide stuff.
      }

  • Orjan says:

    Hello, Thanks for a great plugin!
    I’m having an issue though when it loads in 6 new items it also adds “111111” at the bottom of the new cards. Seems to have something to do with the response in the function.

    If I run the response like this:
    ´$response .= the_title();´
    it works, but in this case I need to run it like this:
    ´$response .= include Apptemplate_path(locate_template('views/partials/cardNews.blade.php'));´
    And it also returns the 1s if I do something like:
    ´$response .= print "hello";´

    Any idea what could be wrong? Thank you

    • Bob Weichler says:

      Hi Orjan,
      Thank you for your message. Can you check in your response what your blade template is returning? – Image Removed – I am assuming it is not returning an HTML-string (like your $response = echo “hello” – you cannot echo inside a variable)

      • Michael says:

        ““
        // use output buffering because get_template_part() loads the part into the template (you cannot append a template part to a string)
        ob_start();
        while ($aktuelles->have_posts()): $aktuelles->the_post();
        get_template_part(‘template-parts/components/card/index’);
        endwhile;
        $markup .= ob_get_contents();
        ob_end_clean();
        ““

    • Elyes Z says:

      Hi orjan,
      The same for me, How you resolved this problem please ?

  • Milito says:

    Just want to leave my comment here that this helped me a lot.

    Thanks!!!

  • Hans Dampf says:

    I am getting “paged is not defined” when using your code to hide the load more button. Any idea? The first part works without problems.

    • Bob Weichler says:

      Hi Hans, thank you for your reply. I am not sure how you’ve implemented my code example, but indeed ‘page’ will not be defined as my code-snippet only gives an example (to show you the logic how I do it and you can tweak it however you need it to be to work with your setup). I have set it as it’s own function, that takes paged as a parameter, like this:

      function loadMore(paged) {
        $.ajax({
          type: 'POST',
          url: '/wp-admin/admin-ajax.php',
          dataType: 'json',
          data: {
            action: 'weichie_load_more',
            paged,
          },
          success: function (res) {
            if(paged >= res.total) {
              $('#load-more').hide();
            }
            $('#jobs-grid-main').append(res.html);
          }
        });
      }

      And then I pass page to my function somewhere else and add page + 1:

      let newPage = 1;
      $('#load-more').on('click', function(){
        loadMore(newPage + 1);
        newPage++;
      });
  • Alessandro Amato says:

    Hey there thanks for the article, it works perfectly! However I wanted to go one step further and combine this with and Ajax filter. So I already have a post filter that pulls in posts depending on the category, but if I also add a load more button at the end it would load the next page of posts regardless of the category of my previous Ajax call – did you find a way to handle a similar case?

    Thank you!

    • Bob Weichler says:

      Hi Alessandro, thank you for your message. To combine the load more with filters, you need to pass your current filters into the load-more function as well. I will try to add a section to this post later this week. But for your JS it would look like this:

      $.ajax({
        type: 'POST',
        url: '/wp-admin/admin-ajax.php',
        dataType: 'json',
        data: {
          action: 'weichie_load_more',
          category: cat_id,
          paged,
        },
        success: function (res) { ... }
      });

      And then in your functions.php you can include the category in your query:

      $ajaxposts = new WP_Query([
          'post_type' => 'publications',
          'posts_per_page' => 6,
          'orderby' => 'date',
          'order' => 'DESC',
          'cat' => $_POST['category'],
          'paged' => $_POST['paged'],
        ]);
      • Alessandro Amato says:

        Hi Bob,
        thanks for your answer. I’m trying this out but I don’t really know how to pass the cat_id to the ajax call – how do you define that?

        I am trying to pass it the way you did in the filter post (awesome as well btw!), but it doesn’t get reset/updated when I use the filter function and the content changes in the dom. Here’s how I structured it

        // load more posts
        let currentPage = 1;
        $("#load-more").on("click", function () {
          currentPage++;
        
          $.ajax({
            type: "POST",
            url: "/wp-admin/admin-ajax.php",
            dataType: "json",
            data: {
              action: "load_more_posts",
              category: $(this).data("slug"),
              paged: currentPage,
            },
            success: function (res) {
              if (currentPage >= res.max) {
                $("#load-more").addClass("hidden");
              }
              $(".showreel").append(res.html);
            },
          });
        });

        and then this in functions.php

        function load_more_posts() {
          $catSlug = $_POST['category'];
          $ajaxposts = new WP_Query([
            'post_type' => 'post',
            'posts_per_page' => 4,
            'orderby' => 'date',
            'order' => 'ASC',
            'category_name' => $catSlug,
            'paged' => $_POST['paged'],
        ]);

        this works at first, but as soon as you reach the end of the results, the load more button is hidden (as it should be) and is never reset; so when I switch the filter I can’t load more posts anymore. Can’t figure out what I’m doing wrong.

        • Bob Weichler says:

          Hi Alessandro, You add the class ‘hidden’ when there are no more posts. But you never remove that class afterwards. You should add an else-statement that removes the hidden-class if there are posts again. (because with ajax, the page never reloads to reset the initial state)

          if (currentPage >= res.max) {
            $('#load-more').addClass('hidden');
          } else {
            $('#load-more').removeClass('hidden');
          }

          Hope it helps!

          • Alessandro Amato says:

            Hey Bob – thanks for the assistance. Unfortunately no, I’m still stuck on trying to make the load_more function work together with the filter. Did you maybe give it a try yourself to update this post? I don’t really know how to pass the category_name to the load_more_posts function once you switch the filter (so the category has changed, e.g. from ‘film’ to ‘photography’ ).

          • Bob Weichler says:

            Hi Alessandro, I’m sorry it’s not working for you. My previous example with the load_more_posts() in our response is a working example of how to combine the pagination & category filters. Another way of doing this is adding a hidden field to your page that stores the current filtered category. Once you click load-more you can read the value from that hidden input field so you’re always loading more posts from that category.
            Hope it helps!

          • Alessandro Amato says:

            Update: I made it work!
            It’s a small thing and also maybe a good addition to your post. You need to reset currentPage to 1 in the filter function, otherwise it will keep trying to load posts from page 2/3/… 🙂

            Thanks for everything!

        • Kasia says:

          Hi Alessandro! I am also trying to add this load more button to a category page. I updated my code to match the updates you made but I am still having issues. Can you update where you added the additional currentPage reset?