Home > Software design >  Fetch WordPress Posts according to custom query with load more button
Fetch WordPress Posts according to custom query with load more button

Time:10-24

I have a 2 row(3-3 column) section on the page. So in the first 5 posts are showing and one is an advertising image.

So in the first row, 2 posts showing then advertising image is showing. And in the second row 3 posts are showing

My code is-

$args = array(  
           'post_type' => 'products',
           'post_status' => 'publish',
           'posts_per_page' => 5,
           'orderby' => 'ID',
           'order' => 'DESC',
        );
  $posts = new WP_Query( $args );

So from this code, I am showing 5 posts and 1 advertising image and it's working fine.

But when I am clicking on the load more button then I need to fetch 6 posts each time so 2 rows(3 posts in a row) will be added.

JS code is

var page = 2;
var ppp = 5;

jQuery("body").on("click", ".btnLoadMoreblog", function(){
   var ajaxUrl = document.location.origin   '/';
   var ajaxurla = ajaxUrl   "wp-admin/admin-ajax.php";
   jQuery('.loading-image img').css('display', 'block');
   jQuery.post(ajaxurla, {
       action: "loadmoreblog",
       ppp: ppp,
       page: page,
   })
   .done(function (postsa) {
       jQuery('.viewmore-btn').before(postsa);
       page  ;
   })
});
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

In the action, this is the code

$ppp = $_POST["ppp"];
$page = $_POST["page"];
$args = array(  
       'post_type' => 'products',
       'post_status' => 'publish',
       'posts_per_page' => $ppp,
       'paged' => $page,
       'orderby' => 'ID',
       'order' => 'DESC',
    );
    $posts = new WP_Query( $args );

The posts are fetching correctly because I pass 5 in ppp variable but the issue is one column is empty.

I want to fetch 6 posts at a time on the ajax load. So if I am passing var ppp = 6; then the posts are not fetching correctly.

CodePudding user response:

What do you mean exactly with "Not fetching correctly".

If no post at all are showing up it could be simply because there are no more posts published.

CodePudding user response:

This is how I load new posts onto the same page using the existing custom WP_Query().

This method also works even with custom url vars which modify the WP_Query().

See my comments in code provided below.

Here is the query php with loops and load more button...

<?php 

// exclude post id's (default false)
$excludePosts = isset($_REQUEST['excludePosts']) ? $_REQUEST['excludePosts'] : false;

// posts per page and load more posts to add
$postsPerPage = 20;

// products query args
$args = [
  'post_type'      => 'products',
  'post_status'    => 'publish',
  'orderby'        => 'ID',
  'order'          => 'DESC',
  'posts_per_page' => $postsPerPage,

  // here is the trick, exclude current posts from query when using jQuery $.post()
  'post__not_in'   => $excludePosts
];

// products query
$products = new WP_Query($args);

?>

<?php // we need this, a parent container for products ?>
<div id="products_archive">

  <?php // if we have query results ?>
  <?php if( $products->have_posts() ): ?>

    <?php // loop our query results (products) ?>
    <?php while( $products->have_posts()): $products->the_post() ?>

      <?php // your product with a data-product attribute and ID as the value ?>
      <?php // we need data-product to find all the currently loaded product ID's ?>
      <article data-product="<?=get_the_id()?>">
        <?php the_title(); ?>
        <?php the_content(); ?>
      </article>

    <?php endwhile; ?>
    
    <?php // if we have more posts to load based on current query, then show button ?>
    <?php if( $products->max_num_pages > 1 ): ?>

      <button id="load_more_products">
        Load more products
      </button>

    <?php endif; ?>

  <?php // if we have no query results ?>
  <?php else: ?>

    Sorry no products found.
  
  <?php endif; ?>

</div>

<?php // we need this, to pass the posts per page value to external jQuery script ?>
<script>
  window.postsPerPage = '<?=$postsPerPage?>';
</script>

Here is the jQuery script using $.post() to reload the current page query excluding products which have already loaded.

// load more products button click event
$(document).on('click', '#load_more_products', function() {

  // our click button
  let $btn = $(this);

  // disable button (you can add spinner to button here too)
  $btn.prop('disabled', true);

  // set current products empty array
  let currentProducts = [];

  // loop thought trough all products in products in archive
  $('[data-product]', '#products_archive').each( function(key, elem) {

    // current product push elements to current products array
    currentProducts.push( $(elem).data('product') );

  });

  // re post current page running the query again
  $.post('', {

    // pass this data to our php var $excludePosts to modify the page WP_Query
    excludePosts: currentProducts

  // html param passed data is full html of our reloaded page
  }, function(html) {

    // find all the product article elements via data-product attribute in html 
    let $newProducts = $('#products_archive [data-product]', html);

    // if new products length is less than our window.postsPerPage variable value
    if( $newProducts.length < postsPerPage ) {

      // then hide the load more button
      $btn.hide();

    }

    // insert new products after last current data-product article
    $newProducts.insertAfter( $('[data-product]', '#products_archive').last() );

  })

  // once our new products have been inserted
  .done(function() {

    // do stuff here to lazy load images etc...

    // re-enable button (and stop button spinner if you have one)
    $btn.prop('disabled', false);

  });

});

Depending on the structure of your current HTML and the placement/appendage of newly fetched products html, you will need to adjust script to suit.

But this should get you on the right track if you follow my code comments.

Good luck!

  • Related