blogob
blogob

Reputation: 530

How to build a load more button and a filtering system with ajax on wordpress?

I managed to build a ajax load more following this tutorial.

I managed to make it work for my blog post on my blog page. So I didn't change anything.

Now I try to make the same for my custom post type, so I simply duplicate all code, changing the variable names :

Here is my custom post type archive page:

<?php 
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'post_type' =>'formation',
'posts_per_page' =>5,
'paged' => $paged
);
$query = new WP_Query( $args ); //Check the WP_Query docs to see how you can limit which posts to display ?>
<?php if ( $query->have_posts() ) : ?>

<div id="cc_formation_wrap" class="flex-row">

<?php while ( $query->have_posts() ) : $query->the_post(); 
    $termsArray = get_the_terms( $post->ID, "categories-formations" );  //Get the terms for this particular item
    $termsString = ""; //initialize the string that will contain the terms
    foreach ( $termsArray as $term ) { // for each term 
    $termsString .= $term->slug.' '; //create a string that has all the slugs } ?>

    <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
        <article id="post-<?php the_ID(); ?>" <?php post_class();?>>
            <div class="isotope-thumbnail">
                <?php 
                if ( has_post_thumbnail() ) { 
                the_post_thumbnail('masonryLayout');
                 }; ?>
            </div>
            <div class="isotope-title">
                <h3><?php the_title(); ?></h3>
            </div>
            <div class="entry-meta">
            <?php    if(get_field('duree')){    
            $duree = get_field_object('duree');
            echo '<div><span class="isotope-duree">' .  get_field('duree') . '</span></div>';}?>
            </div>
            <div class="isotope-excerpt">
                <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
            </div>
            <div class="isotope-cta">
                <a href="<?php esc_url( the_permalink() );?>" rel="bookmark">Voir</a>
            </div>
        </article>
    </div>
    <!-- end item -->

    <?php endwhile;  ?>
</div>
<!-- end isotope-list -->
<?php   
global $wp_query;  
if (  $wp_query->max_num_pages > 1 ) :
echo '<div id="cc_formation_loadmore">More posts</div>';
endif;
else :
get_template_part( 'template-parts/content', 'none' );
endif;  ?>

Here is the code for functions.php file :

/*FITLERING AND LOADING MORE ON FORMATION PAGE*/
add_action( 'wp_enqueue_scripts', 'cc_formation_script_and_styles');
function cc_formation_script_and_styles() {
    if( is_post_type_archive('formation') ){
    global $wp_query;
    wp_register_script( 'load-more', get_stylesheet_directory_uri() . '/js/load-more.js', array('jquery') );
    wp_localize_script( 'load-more', 'cc_formation_loadmore_params', array(
        'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
        'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
        'current_page' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
        'max_page' =>$wp_query->max_num_pages
    ) );

    wp_enqueue_script( 'load-more' );
 }
}


add_action('wp_ajax_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');

function cc_formation_loadmore_ajax_handler(){

    $args = json_decode( stripslashes( $_POST['query'] ), true ); 
    $args['paged'] = $_POST['page'] + 1; 
    $args['post_status'] = 'publish';
    $args["post_type"] = 'formation';


    query_posts( $args );
    if( have_posts() ) :
        while( have_posts() ): the_post();  
        $termsArray = get_the_terms($post->ID, "categories-formations");  
         $termsString =""; 
         foreach ( $termsArray as $term ) {
         $termsString .= $term->slug;  
         }
         ?>
            <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
                <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                    <div class="isotope-thumbnail">
                     <?php 
                        if ( has_post_thumbnail() ) { 
                                      the_post_thumbnail('masonryLayout');
                                } ;
                        ?>
                    </div>
                    <div class="isotope-title">
                        <h3><?php the_title(); ?></h3>
                    </div>
                    <div class="isotope-excerpt">
                        <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
                    </div>
                    <div class="isotope-cta">
                        <a href="<?php esc_url( get_permalink() );?>" rel="bookmark">Voir</a>
                    </div>
                </article>
             </div> <!-- end item -->
            <?php
        endwhile;
    endif;

    die; 
}    
add_action('wp_ajax_ccformationfilter', 'cc_formation_filter_function'); 
add_action('wp_ajax_nopriv_ccformationfilter', 'cc_formation_filter_function');



function cc_formation_filter_function(){
            $args = array(
                'post_type' => 'formation',
                'post_per_page'=>5,
                'tax_query' => array(
                    array(
                        'taxonomy' => 'categories-formations',
                        'field'    => 'slug',
                        'terms' => array('git','python','django','unix')
                    )
                ),
            );

            // run the query
    query_posts( $args );
    if( have_posts() ) :
        ob_start(); 
        while( have_posts() ): the_post();

            $termsArray = get_the_terms($post->ID, "categories-formations");  
             $termsString =""; 
             foreach ( $termsArray as $term ) { 
             $termsString .= $term->slug;  
             }
             ?>
            <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
                <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                    <div class="isotope-thumbnail">
                     <?php 
                        if ( has_post_thumbnail() ) { 
                                      the_post_thumbnail('masonryLayout');
                                } 
                        ?>
                    </div>
                    <div class="isotope-title">
                        <h3><?php the_title(); ?></h3>
                    </div>
                    <div class="entry-meta">
                            <?php    if(get_field('duree')){    
                                $duree = get_field_object('duree');
                                echo '<div><span class="isotope-duree">' .  get_field('duree') . '</span></div>';
                                }
                            ?>
                        </div>
                    <div class="isotope-excerpt">
                        <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
                    </div>
                    <div class="isotope-cta">
                        <a href="<?php esc_url( get_post_permalink($post->ID) );?>" rel="bookmark">Voir</a>
                    </div>
                </article>
             </div> <!-- end item -->

            <?php

        endwhile;
        $posts_html = ob_get_contents(); 
        ob_end_clean(); 
    else:
        $posts_html = '<p>Nothing found for your criteria.</p>';
    endif;
    echo json_encode( array(
        'posts' => json_encode( $wp_query->query_vars ),
        'max_page' => $wp_query->max_num_pages,
        'found_posts' => $wp_query->found_posts,
        'content' => $posts_html
    ) );

    die();
}

So I changed the ajax action name, the params function etc. I kept the global wp_query but don't know if I also have to change that.

Then in a separate js file I put the following :

jQuery(function($){

/* LOAD MORE FUNCTION ON FORMATION ARCHIVE PAGE */
$('#cc_formation_loadmore').click(function(){

$.ajax({
  url : cc_formation_loadmore_params.ajaxurl, // AJAX handler
  data : {
    'action': 'loadmoreformationbutton', // the parameter for admin-ajax.php
    'query': cc_formation_loadmore_params.posts, // loop parameters passed by wp_localize_script()
    'page' : cc_formation_loadmore_params.current_page // current page
  },
  type : 'POST',
  beforeSend : function ( xhr ) {
    $('#cc_formation_loadmore').text('Loading...'); // some type of preloader
  },
  success : function( posts ){
    if( posts ) {

      $('#cc_formation_loadmore').text( 'More posts' );
      $('#cc_formation_wrap').append( posts ); // insert new posts
      cc_formation_loadmore_params.current_page++;

      if ( cc_formation_loadmore_params.current_page == cc_formation_loadmore_params.max_page ) 
        $('#cc_formation_loadmore').hide(); // if last page, HIDE the button

    } else {
      $('#cc_formation_loadmore').hide(); // if no data, HIDE the button as well
    }
  }
});
return false;
});
/* FILTERING FUNCTION ON FORMATION ARCHIVE PAGE */
$('#formation_filters').change(function(){
 $.ajax({
  url : cc_formation_loadmore_params.ajaxurl,
  data : $('#formation_filters').serialize(), // form data
  dataType : 'json', // this data type allows us to receive objects from the server
  type : 'POST',

  success : function( data ){
    // when filter applied:
    // set the current page to 1
    cc_formation_loadmore_params.current_page = 1; 
    // set the new query parameters
    cc_formation_loadmore_params.posts = data.posts;
    // set the new max page parameter
    cc_formation_loadmore_params.max_page = data.max_page; 
    // change the button label back
    // insert the posts to the container
    $('#cc_formation_wrap').html(data.content); 
    // hide load more button, if there are not enough posts for the second page
    if ( data.max_page < 2 ) {
      $('#cc_formation_loadmore').hide();
    } else {
      $('#cc_formation_loadmore').show();
    }
  }
});
// do not submit the form
return false;

 });

 });

With this, the load more works. It displays the next custom posts type on my archive page.

But the filtering function doens't work.

So I need help to understand which variables I have to change. When I click on a filter checkbox, it first loads my blog post, and then the others filtering chekcbox don't work. So I don't understand why it calls my blog posts.. What am I doing wrong ????

Looking for advice on this.

Thanks

Upvotes: 0

Views: 5741

Answers (2)

blogob
blogob

Reputation: 530

Ok i finaly found my solultion !

1-In my project I first build a blog page (with normal blog posts) with categories filters and an ajax load more button.

Here is the code in my home.php

<?php
/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * E.g., it puts together the home page when no home.php file exists.
 *
 * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
 *
 * @package mysite
 */

get_header();
?>

    <div id="primary" class="content-area">
        <main id="main" class="site-main">
            <div class="flex-container">
                <div class="flex-row">  
                    <header class="page-header">
                        <?php
                        single_post_title('<h1 class="page-title">', '</h1>' );

                        ?>
                    </header><!-- .page-header -->
                </div>
                <div class="flex-row">
                    <form action="#" method="POST" id="post_filters">
                        <p><a href="" id="clear">Clear</a></p>
                        <?php 
                        if( $terms = get_terms( array( 'taxonomy' => 'category' ) ) ) :
                            foreach( $terms as $term ) :
                                echo '<p><input type="radio" id="' . $term->term_id . '" value="' . $term->term_id . '" name="category_filters" class="category_filter"/><label for="' . $term->term_id. '">' . $term->name . '</label></p>';
                            endforeach;
                        endif;
                        ?>
                        <!-- required hidden field for admin-ajax.php -->
                        <input type="hidden" name="action" value="ccfilter" />
                    </form>
                </div>



                <?php
                $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
                $args = array(
                    'post_type' => 'post',
                    'post_status' => 'publish',
                    'posts_per_page' => 5,
                    'paged' => $paged

                );
                $query = new WP_Query( $args ); ?>
                <?php 
                if ( $query->have_posts() ) :
                $count = (int)0;?>
                    <div id="cc_posts_wrap" class="flex-row">
                        <?php
                        while ( $query->have_posts() ) : $count++;
                            $query->the_post();
                            if($count == 1){
                                $span = 'flex-col-xs-12';
                                $limit = 20;


                            }
                            if($count == 2 || $count == 3){
                            $span = 'flex-col-sm-6';
                            $limit = 13;
                            }
                            if($count > 3){
                            $span = 'flex-col-sm-4';
                            $limit = 13;
                            }
                            //If its not 3 or higher, increase the count
                            $termsArray = get_the_terms($post->ID, "category");  //Get the terms for this particular item
                             $termsString =""; //initialize the string that will contain the terms
                             foreach ( $termsArray as $term ) { // for each term 
                             $termsString .= $term->slug;  
                             }
                        ?>
                                 <div  class="<?php echo $termsString  .' ' . $span ;?> item">
                                    <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                                        <div class="post-featured-thumbnail">
                                            <?php   
                                                if ( has_post_thumbnail() ) { 
                                                    if($count == 1){
                                                    the_post_thumbnail('blog_featured');                                        
                                                }else{
                                                    the_post_thumbnail();
                                                }
                                            }

                                             if ( 'post' === get_post_type() ) :
                                                ?>
                                                <div class="entry-meta">
                                                    <?php
                                                    category_sticker();     
                                                    ?>
                                                </div><!-- .entry-meta -->
                                            <?php endif; ?>
                                        </div>
                                        <div class="post-content">
                                            <header class="entry-header">
                                                <?php
                                                if ( is_singular() ) :
                                                    the_title( '<h1 class="entry-title">', '</h1>' );
                                                else :
                                                    the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
                                                endif;
                                                ?>
                                            </header><!-- .entry-header -->
                                            <div class="entry-content">
                                                <?php echo excerpt($limit); ?>
                                            </div><!-- .entry-content -->
                                        </div>
                                    </article><!-- #post-<?php the_ID(); ?> -->
                                </div>


                <?php       endwhile;
                ?>  
                </div> <!-- end isotope-list -->                    

                <?php   global $wp_query; // you can remove this line if everything works for you

            if (  $wp_query->max_num_pages > 1 ) :
                echo '<div id="cc_loadmore">More posts</div>'; // you can use <a> as well
            endif;



        else :

            get_template_part( 'template-parts/content', 'none' );

                    endif;
    ?>
        </div>
        </main><!-- #main -->
    </div><!-- #primary -->

<?php

get_footer();

Then in function php, the code for the load more button and the filters functions :

    /*FUNCTION FILTER AND AJAX LOAD MORE*/
    add_action( 'wp_enqueue_scripts', 'cc_script_and_styles');
    function cc_script_and_styles() {
        if ( is_home() ) {
        global $wp_query;
        wp_register_script( 'cc_scripts', get_stylesheet_directory_uri() . '/js/script.js', array('jquery') );
        wp_localize_script( 'cc_scripts', 'cc_loadmore_params', array(
            'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
            'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
            'current_page' => $wp_query->query_vars['paged'] ? $wp_query->query_vars['paged'] : 1,
            'max_page' => $wp_query->max_num_pages
        ) );

        wp_enqueue_script( 'cc_scripts' );
     }
    }

    add_action('wp_ajax_loadmorebutton', 'cc_loadmore_ajax_handler');
    add_action('wp_ajax_nopriv_loadmorebutton', 'cc_loadmore_ajax_handler');

    function cc_loadmore_ajax_handler(){

        $params = json_decode( stripslashes( $_POST['query'] ), true ); 
        $params['paged'] = $_POST['page'] + 1; 
        $params['post_status'] = 'publish';


        query_posts( $params );

        if( have_posts() ) :


            while( have_posts() ): the_post();

                $termsArray = get_the_terms($post->ID, "category");  
                 $termsString =""; 
                 foreach ( $termsArray as $term ) {
                 $termsString .= $term->slug;  
                 }
                 ?>
                <div  class="<?php echo $termsString ;?> flex-col-sm-4 item">
                    <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                        <div class="post-featured-thumbnail">
                            <?php   
                                if ( has_post_thumbnail() ) { 
                            if($count == 1){
                                 the_post_thumbnail('blog_featured');                                       
                                }else{
                                the_post_thumbnail();
                                }
                            }
                             ;
                             if ( 'post' === get_post_type() ) :
                                ?>
                                <div class="entry-meta">
                                    <?php
                                    category_sticker();     
                                    ?>
                                </div><!-- .entry-meta -->
                            <?php endif; ?>
                        </div>
                        <div class="post-content">
                            <header class="entry-header">
                                <?php
                                if ( is_singular() ) :
                                    the_title( '<h1 class="entry-title">', '</h1>' );
                                else :
                                    the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
                                endif;
                                ?>
                            </header><!-- .entry-header -->
                            <div class="entry-content">
                                <?php echo excerpt($limit); ?>
                            </div><!-- .entry-content -->
                        </div>
                    </article><!-- #post-<?php the_ID(); ?> -->
                </div>
                <?php
            endwhile;

        endif;


        die; 
    }




add_action('wp_ajax_ccfilter', 'cc_filter_function'); 
add_action('wp_ajax_nopriv_ccfilter', 'cc_filter_function');

function cc_filter_function(){


    if( isset( $_POST['category_filters'] ) )
        $args['tax_query'] = array(
            array(
                'taxonomy' => 'category',
                'field' => 'id',
                'terms' => $_POST['category_filters'],
                "posts_per_page" => 5
            )
        );
        query_posts( $args );

    global $wp_query;

    if( have_posts() ) : $count = (int)0;

        ob_start(); 

        while( have_posts() ): $count++;
        the_post();
        if($count == 1){
                $span = 'flex-col-xs-12';
                $limit = 20;


            }
            if($count == 2 || $count == 3){
            $span = 'flex-col-sm-6';
            $limit = 13;
            }
            if($count > 3){
            $span = 'flex-col-sm-4';
            $limit = 13;
            }

            $termsArray = get_the_terms($post->ID, "category");  
             $termsString =""; 
             foreach ( $termsArray as $term ) { 
             $termsString .= $term->slug;  
             }
             ?>
            <div  class="<?php echo $termsString  .' ' . $span ;?> item">
                <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                    <div class="post-featured-thumbnail">
                        <?php   
                            if ( has_post_thumbnail() ) { 
                        if($count == 1){
                             the_post_thumbnail('blog_featured');                                       
                            }else{
                            the_post_thumbnail();
                            }
                        }
                         ;
                         if ( 'post' === get_post_type() ) :
                            ?>
                            <div class="entry-meta">
                                <?php
                                category_sticker();     
                                ?>
                            </div><!-- .entry-meta -->
                        <?php endif; ?>
                    </div>
                    <div class="post-content">
                        <header class="entry-header">
                            <?php
                            if ( is_singular() ) :
                                the_title( '<h1 class="entry-title">', '</h1>' );
                            else :
                                the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
                            endif;
                            ?>
                        </header><!-- .entry-header -->
                        <div class="entry-content">
                            <?php echo excerpt($limit); ?>
                        </div><!-- .entry-content -->
                    </div>
                </article><!-- #post-<?php the_ID(); ?> -->
            </div>

            <?php

        endwhile;

        $posts_html = ob_get_contents(); 
        ob_end_clean(); 
    else:
        $posts_html = '<p>Nothing found for your criteria.</p>';
    endif;

    echo json_encode( array(
        'posts' => json_encode( $wp_query->query_vars ),
        'max_page' => $wp_query->max_num_pages,
        'found_posts' => $wp_query->found_posts,
        'content' => $posts_html
    ) );

    die();
}

Then, in a separate js file, the functions for the load more button and filters function :

jQuery(function($){

/* LOAD MORE FUNCTION */
$('#cc_loadmore').click(function(){

  $.ajax({
    url : cc_loadmore_params.ajaxurl, // AJAX handler
    data : {
      'action': 'loadmorebutton', // the parameter for admin-ajax.php
      'query': cc_loadmore_params.posts, // loop parameters passed by wp_localize_script()
      'page' : cc_loadmore_params.current_page // current page
    },
    type : 'POST',
    beforeSend : function ( xhr ) {
      $('#cc_loadmore').text('Loading...'); // some type of preloader
    },
    success : function( posts ){
      if( posts ) {

        $('#cc_loadmore').text( 'More posts' );
        $('#cc_posts_wrap').append( posts ); // insert new posts
        cc_loadmore_params.current_page++;

        if ( cc_loadmore_params.current_page == cc_loadmore_params.max_page ) 
          $('#cc_loadmore').hide(); // if last page, HIDE the button

      } else {
        $('#cc_loadmore').hide(); // if no data, HIDE the button as well
      }
    }
  });
  return false;
});
/* FILTERING FUNCTION */
$('#post_filters').change(function(){

  $.ajax({
    url : cc_loadmore_params.ajaxurl,
    data : $('#post_filters').serialize(), // form data
    dataType : 'json', // this data type allows us to receive objects from the server
    type : 'POST',

    success : function( data ){
      cc_loadmore_params.current_page = 1; 
      cc_loadmore_params.posts = data.posts;
      cc_loadmore_params.max_page = data.max_page; 

      $('#cc_posts_wrap').html(data.content); 
      if ( data.max_page < 2 ) {
        $('#cc_loadmore').hide();
      } else {
        $('#cc_loadmore').show();
      }
    }
  });
  return false;

});   });

For blog posts, it's done and it works !

Explanations :

  • As you can see here, in functions.php, and the cc_script_and_styles function, and the -'cc_loadmore_params' are used everywhere in the js file. Be careful to write the same function in all places!

  • The action of the ajax call in the js file, 'loadmorebutton', is the same name than in the hook 'wp_ajax_loadmorebutton' in functions.php

    add_action('wp_ajax_loadmorebutton', 'cc_loadmore_ajax_handler'); add_action('wp_ajax_nopriv_loadmorebutton', 'cc_loadmore_ajax_handler');

  • The value of the hidden input in home.php : 'ccfilter' is the same than in the hook of the function cc_filter_function(){

and

add_action('wp_ajax_ccfilter', 'cc_filter_function'); 
add_action('wp_ajax_nopriv_ccfilter', 'cc_filter_function');
  • Now, we also want to add similar filters and a load more button for a custom post type.

Here is my custom post type archive :

get_header();
?>

<div id="primary" class="content-area">
    <main id="main" class="site-main">
        <div class="flex-container">
            <div class="flex-row">  
                <header class="page-header">
                    <?php
                    post_type_archive_title( '<h1 class="page-title">', '</h1>' );

                    ?>
                </header><!-- .page-header -->
            </div>
            <div class="flex-row">
                <form action="#" method="POST" id="formation_filters">
                    <p><a href="" id="clear">Clear</a></p>
                    <?php 
                    if( $terms = get_terms( array( 'taxonomy' => 'categories-formations' ) ) ) :
                        foreach( $terms as $term ) :
                            echo '<p><input type="radio" id="' . $term->term_id . '" value="' . $term->term_id . '" name="category_formation_filters" class="category_formation_filters"/><label for="' . $term->term_id. '">' . $term->name . '</label></p>';
                        endforeach;
                    endif;
                    ?>
                    <!-- required hidden field for admin-ajax.php -->
                    <input type="hidden" name="action" value="ccformationfilter" />
                </form>
            </div>

               <?php 
                $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
                $args=array(
                'post_type' =>'formation',
                'posts_per_page' =>5,
                'paged' => $paged

                );
                $query = new WP_Query( $args );?>
                <?php if ( $query->have_posts() ) : ?>
                <div id="cc_formation_wrap" class="flex-row">
                    <?php while ( $query->have_posts() ) : $query->the_post(); 
                        $termsArray = get_the_terms( $post->ID, "categories-formations" );  
                        $termsString = ""; 
                        foreach ( $termsArray as $term ) {
                        $termsString .= $term->slug.' ';  
                        }
                        ?> 
                        <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
                        <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                            <div class="isotope-thumbnail">
                             <?php 
                                if ( has_post_thumbnail() ) { 
                                              the_post_thumbnail('masonryLayout');
                                        } ;
                                ?>
                            </div>
                            <div class="isotope-title">
                                <h3><?php the_title(); ?></h3>
                            </div>
                            <div class="entry-meta">
                                    <?php    if(get_field('duree')){    
                                        $duree = get_field_object('duree');
                                        echo '<div><span class="isotope-duree">' .  get_field('duree') . '</span></div>';
                                        }
                                    ?>
                                </div>
                            <div class="isotope-excerpt">
                                <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
                            </div>
                            <div class="isotope-cta">
                                <a href="<?php esc_url( the_permalink() );?>" rel="bookmark">Voir</a>
                            </div>
                        </article>
                     </div> <!-- end item -->

                    <?php endwhile;  
                    ?>
                </div> <!-- end isotope-list -->

                <?php   

                if (  $query->max_num_pages > 1 ) :
                    echo '<div id="cc_formation_loadmore">More posts</div>'; 
                endif;
                else :
                get_template_part( 'template-parts/content', 'none' );
                endif;  ?>

        </div>
    </main>
</div>
<script>
    var posts_myajax = '<?php echo serialize( $query->query_vars ) ?>',
    current_page_myajax = 1,
    max_page_myajax = <?php echo $query->max_num_pages ?>
</script>
<script src="<?php bloginfo('template_url')?>/js/load-more.js"></script>
<?php get_footer();?>

Here we build the same type of filters, we just changed the name of the taxonomy, and declare the post_type parameter. We make our ajax call at the bottom of the file with new variables names. And we call a separate js file load-more.js.

In order to keep clean structure, I also created a separate file called : formation-query.php. In functions.php, I call it with:

require get_template_directory() . '/inc/formation-query.php';

We don't duplicate the function cc_script_and_styles() { We just create our two functions for load more and filters with new variables names.

add_action('wp_ajax_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');
add_action('wp_ajax_nopriv_loadmoreformationbutton', 'cc_formation_loadmore_ajax_handler');

function cc_formation_loadmore_ajax_handler(){

$args = json_decode( stripslashes( $_POST['query'] ), true ); 
$args['paged'] = $_POST['page'] + 1; 
$args['post_status'] = 'publish';
$args["post_type"] = 'formation';


query_posts( $args );
global $wp_query;
if( have_posts() ) :
    while( have_posts() ): the_post();
        $termsArray = get_the_terms($post->ID, "categories-formations");  
         $termsString =""; 
         foreach ( $termsArray as $term ) {
         $termsString .= $term->slug;  
         }
         ?>
        <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
            <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                <div class="isotope-thumbnail">
                 <?php 
                    if ( has_post_thumbnail() ) { 
                                  the_post_thumbnail('masonryLayout');
                            } ;
                    ?>
                </div>
                <div class="isotope-title">
                    <h3><?php the_title(); ?></h3>
                </div>
                <div class="isotope-excerpt">
                    <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
                </div>
                <div class="isotope-cta">
                    <a href="<?php esc_url( get_permalink() );?>" rel="bookmark">Voir</a>
                </div>
            </article>
         </div> <!-- end item -->
        <?php
    endwhile;

endif;

die; 
}

add_action('wp_ajax_ccformationfilter', 'cc_formation_filter_function'); 
add_action('wp_ajax_nopriv_ccformationfilter', 'cc_formation_filter_function');



function cc_formation_filter_function(){                       
    $args["post_type"] = 'formation';
        $args['tax_query'] = array(
            array(
                'taxonomy' => 'categories-formations',
                'field' => 'id',
                'terms' => $_POST['category_formation_filters'],
                "posts_per_page" => 5
            )
        );


    $query = new WP_Query($args);
    if( $query->have_posts() ) :
        ob_start(); 
        while( $query->have_posts() ): $query->the_post();

            $termsArray = get_the_terms($post->ID, "categories-formations");  
             $termsString =""; 
             foreach ( $termsArray as $term ) { 
             $termsString .= $term->slug;  
             }
             ?>
            <div class="<?php echo $termsString;?> flex-col-md-4 item related-formation-post">
                <article  id="post-<?php the_ID(); ?>" <?php post_class();?>>
                    <div class="isotope-thumbnail">
                     <?php 
                        if ( has_post_thumbnail() ) { 
                                      the_post_thumbnail('masonryLayout');
                                } 
                        ?>
                    </div>
                    <div class="isotope-title">
                        <h3><?php the_title(); ?></h3>
                    </div>
                    <div class="entry-meta">
                            <?php    if(get_field('duree')){    
                                $duree = get_field_object('duree');
                                echo '<div><span class="isotope-duree">' .  get_field('duree') . '</span></div>';
                                }
                            ?>
                        </div>
                    <div class="isotope-excerpt">
                        <?php echo get_post_meta(get_the_ID(), '_yoast_wpseo_metadesc', true); ?>
                    </div>
                    <div class="isotope-cta">
                        <a href="<?php esc_url( get_post_permalink($post->ID) );?>" rel="bookmark">Voir</a>
                    </div>
                </article>
             </div> <!-- end item -->
            <?php                    
        endwhile;                           
        $posts_html = ob_get_contents(); 
        ob_end_clean(); 
    else:
        $posts_html = '<p>Nothing found for your criteria.</p>';
    endif;
    echo json_encode( array(
        'posts' => json_encode( $query->query_vars ),
        'max_page' => $query->max_num_pages,
        'found_posts' => $query->found_posts,
        'content' => $posts_html
    ) );
    die();
}

Now in a separate load-more.js file :

/* LOAD MORE FUNCTION ON FORMATION ARCHIVE PAGE */
$('#cc_formation_loadmore').click(function(){          
   data = {
    'action': 'loadmoreformationbutton',
    'query': posts_myajax,
    'page' : current_page_myajax
  };

  $.ajax({
    url : '/mysite/wp-admin/admin-ajax.php', // AJAX handler
    data : data,
    type : 'POST',
    beforeSend : function ( xhr ) {
      $('#cc_formation_loadmore').text('Loading...');
    },
    success : function( posts ){
      if( posts ) {

        $('#cc_formation_loadmore').text( 'More posts' );
        $('#cc_formation_wrap').append( posts );
       current_page_myajax++;

        if ( current_page_myajax == max_page_myajax )
          $('#cc_formation_loadmore').hide();          
      } else {
        $('#cc_formation_loadmore').hide();
      }
    }
  });
  return false;
});
/* FILTERING FUNCTION ON FORMATION ARCHIVE PAGE */
$('#formation_filters').change(function(){
  $.ajax({
    url : '/mysite/wp-admin/admin-ajax.php',
    data : $('#formation_filters').serialize(),
    dataType : 'json',
    type : 'POST',

    success : function( data ){
      current_page_myajax = 1; 
      posts_myajax = data.posts;
      max_page_myajax = data.max_page; 
      $('#cc_formation_wrap').html(data.content); 
      if ( data.max_page < 2 ) {
        $('#cc_formation_loadmore').hide();
      } else {
        $('#cc_formation_loadmore').show();
      }
    }
  });
   return false;

});

});

As you can see,

  • The 'loadmoreformationbutton' in the hook is the ajax action name in the js file.

  • The value of hidden input in the form 'ccformationfilter' is the name of the filter ajax function.

Now you can duplicate this if you need others load more buttons and filters for other custom post type !

It took me a while before understanding that function names had to be the same in every file. The different loops are of course also important.

Upvotes: 2

Dmytro Koval
Dmytro Koval

Reputation: 51

As an option, you could avoid PITA with your own code followed by tutorial by using the pre-built plugin to achieve Ajax Load More and filtering in Wordpress. https://wordpress.org/plugins/ajax-load-more/

It's a really good one I've used multiple times to implement Load More by Ajax in my websites.

The free version has plenty of features.

Upvotes: 1

Related Questions