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">
Voir
</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">
Voir
</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">
Voir
</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
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>Clear</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">', '</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">', '</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">', '</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>Clear</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">
Voir
</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">
Voir
</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">
Voir
</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.
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.
Using WordPress, I'm trying to load my posts content in a popup div using AJAX, but I can't seem to be able to make it work. I think I'm on the right tracks, but I'm not really a developer, so I need some help!
I want to achieve something like this. So here's my (relevant) code so far:
In my page portfolio.php:
<div id="popUp">
<div class="fermePop">X</div>
<div id="contenuPop"></div>
</div>
...
if ( $query->have_posts() ): ?>
<div class="tagged-posts">
<?php while ( $query->have_posts() ) : $query->the_post(); ?>
<a href="<?php the_permalink(); ?>" <?php post_class( 'tiles' ); ?> rel="<?php the_ID(); ?>">
<?php the_post_thumbnail(); ?>
<h2><?php the_title(); ?></h2>
</a>
<?php endwhile; ?>
</div>
<?php else: ?>
<div class="tagged-posts">
<h2>No posts found</h2>
</div>
<?php endif; ?>
Single.php
<?php
function is_ajax() {
return isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}
if (is_ajax()) {
get_header();
} ?>
<?php if (have_posts()) :
while (have_posts()) : the_post(); ?>
<div id="single-post post-<?php the_ID(); ?>">
<h2><?php the_title(); ?></h2>
<div class="contenu">
<?php the_content(); ?>
</div>
</div>
<?php endwhile; ?>
<?php endif; ?>
<?php
if (is_ajax()) {
get_footer();
}
?>
function.php
function ajax_load_projets(){
wp_register_script('ajax_load_projets', get_template_directory_uri() . '/js/ajax-load-projets.js', false, null, false);
wp_enqueue_script('ajax_load_projets');
wp_localize_script('ajax_load_projets', 'load_projets_vars', array(
'load_projets_ajaxurl' => admin_url('admin-ajax.php'),
)
);
}
add_action( 'wp_enqueue_scripts', 'ajax_load_projets' );
add_action('wp_ajax_load-single-post', 'prefix_ajax_single_post');
add_action('wp_ajax_nopriv_load-single-post', 'prefix_ajax_single_post');
function prefix_ajax_single_post() {
$pid = (int) filter_input(INPUT_GET, 'pID', FILTSER_SANITIZE_NUMBER_INT);
if ($pid > 0) {
global $post;
$post = get_post($pid);
setup_postdata($post);
printf('<div id="single-post post-%d">', $pid);
the_title();
the_content();
echo '</div>';
}
exit();
}
And finaly, my JQuery script :
jQuery(document).ready(function($) {
$.ajaxSetup({cache:false});
$(".tiles").click(function(event){
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
var postID = $(this).attr('rel');
var $container = $("#contenuPop");
$('.filtre').show();
$("#popUp").show();
$container.html("Je charge!");
data={
action: 'prefix_ajax_single_post',
pID: postID,
};
$.post(load_projets_vars.load_projets_ajaxurl, data, function(content) {
$container.html(content);
});
});
function fermePop(){
$('.filtre').hide();
$("#popUp").hide();
}
$(".filtre").click(function(){
fermePop();
});
$(".fermePop").click(function(){
fermePop();
});
});
It's my first time using ajax, so I'm not sure what I'm doing wrong.
Try this.
function prefix_ajax_single_post() {
$pid = $_REQUEST['pID'];
if ($pid > 0) {
global $post;
$post = get_post($pid);
setup_postdata($post);
printf('<div id="single-post post-%d">', $pid);
the_title();
the_content();
echo '</div>';
}
exit();
}
add_action('wp_ajax_prefix_ajax_single_post', 'prefix_ajax_single_post');
add_action('wp_ajax_nopriv_prefix_ajax_single_post', 'prefix_ajax_single_post');
You're not getting the $pid correctly in the prefix_ajax_single_post() function. Since you're posting the data you can do:
$pid = $_POST['pID'];
I have edited Comment module from a tutorial to review module.
In this module i using CStarRating widget. When view, submit, delete rate post it OK. but when i click edit/update, edit old post and click update to edit rate post then star don't show, instead this radio group ???
Here is code:
CommentList.php
<?php
/** #var CArrayDataProvider $comments */
$comments = $model->getCommentDataProvider();
$comments->setPagination(false);
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$comments,
'itemView'=>'comment.views.comment._view'
));
$this->renderPartial('comment.views.comment._form', array(
'comment'=>$model->commentInstance
));
_view.php
<?php
?>
<nav id = "atext" >
<div>
<span class="ext-comment-head">
wrote on
<span class="ext-comment-date">
<?php echo Yii::app()->format->formatDateTime(
is_numeric($data->createDate) ? $data->createDate : strtotime($data->createDate)
);
?>
</span>
</span>
<span class="ext-comment-options">
<?php if (!Yii::app()->user->isGuest && (Yii::app()->user->id == $data->userId)) {
echo CHtml::ajaxLink('delete', array('/comment/comment/delete', 'id'=>$data->id), array(
'success'=>'function(){ $("#ext-comment-'.$data->id.'").remove(); }',
'type'=>'POST',
), array(
'id'=>'delete-comment-'.$data->id,
'confirm'=>'Are you sure you want to delete this item?',
));
echo " | ";
echo CHtml::ajaxLink('edit', array('/comment/comment/update', 'id'=>$data->id), array(
'replace'=>'#ext-comment-'.$data->id,
'type'=>'GET',
), array(
'id'=>'ext-comment-edit-'.$data->id,
));
} ?>
</span>
<p id = "apa">
<br>
</p>
<table id = "atable">
<td id = "test123">
<?php
$model=new Comment;
$a=$data->id;
$colArr=$model->attributes;
for ($i = 0; $i < count($colArr); $i++) {
$key=key($colArr);
$val=$colArr[$key];
next($colArr);
if (($key<> 'average') and($key<>'id') and ($key<>'message')
and ($key<>'userId') and ($key<>'createDate') ) {
$a=$a+100;
echo $data->getAttributeLabel($key).' ('.$data->$key.')';
$this->widget('CStarRating',array(
'name'=>'Comment['.$a.']',
'value'=>$data->$key,
'minRating'=>1, //minimal value
'maxRating'=>5,//max value
'starCount'=>5, //number of stars
'readOnly'=>true,
));
}
echo "<br>";
}
?>
</td>
<td id = "average-teacher">
<p>
<?php echo nl2br(CHtml::encode($data->message)); ?>
</p>
</td>
</table>
<br style="clear: both;"/>
</div>
</nav>
</div>
_form.php
<br>
<br>
<?php if (Yii::app()->user->isGuest) {
?><div class="ext-comment-not-loggedin">
Sorry, you have to login to leave a comment.
</div><?php } else { ?>
<div id="ext-comment-form-<?php echo $comment->isNewRecord ? 'new' : 'edit-'.$comment->id; ?>" class="form" >
<nav id = "comment-a">
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'ext-comment-form',
'action'=>array('/comment/comment/create'),
'enableAjaxValidation'=>false
)); ?>
<?php /** #var CActiveForm $form */
echo $form->errorSummary($comment); ?>
<div class="row">
<?php echo $form->labelEx($comment,'message'); ?>
<?php echo $form->textArea($comment,'message',array('rows'=>3, 'cols'=>76)); ?>
<?php echo $form->error($comment,'message'); ?>
</div>
<?php
$model=new Comment;
$colArr=$model->attributes;
for ($i = 0; $i < count($colArr); $i++) {
$key=key($colArr);
if (($key<> 'average') and ($key<>'id') and ($key<>'message') and ($key<>'userId')
and ($key<>'createDate') ){
$this->widget('CStarRating',array(
'name'=>'Comment['.$key.']',
'value'=>$model->$key,
'minRating'=>1, //minimal value
'maxRating'=>5,//max value
'starCount'=>5, //number of stars
));
echo " ".$model->getAttributeLabel($key)."<br>";
echo "<br>";}
next($colArr);
}
?>
<div class="row buttons">
<?php if ($comment->isNewRecord) {
echo "<br>";
echo $form->hiddenField($comment, 'type');
echo $form->hiddenField($comment, 'key');
echo CHtml::ajaxSubmitButton('Submit',
array('/comment/comment/create'),
array(
'replace'=>'#ext-comment-form-new',
'error'=>"function(){
$('#Comment_message').css('border-color', 'red');
$('#Comment_message').css('background-color', '#fcc');
}"
),
array('id'=>'ext-comment-submit' . (isset($ajaxId) ? $ajaxId : ''))
);
} else {
echo CHtml::ajaxSubmitButton('Update',
array('/comment/comment/update', 'id'=>$comment->id),
array(
'replace'=>'#ext-comment-form-edit-'.$comment->id,
'error'=>"function(){
$('#Comment_message').css('border-color', 'red');
$('#Comment_message').css('background-color', '#fcc');
}"
),
array('id'=>'ext-comment-submit' . (isset($ajaxId) ? $ajaxId : ''))
);
}
echo "<br>";
?>
</div>
<?php $this->endWidget() ?>
</nav>
</div><!-- form -->
<?php } ?>
Hope someone can help me :( And sorry about my english :(
I have a problem when using multiple ajaxLink for loading CJuiDialog widget in yii. I'm using multiple dropdowns, each dropdown's value determine next dropdown.
Here is my code for viewing first dropdown and a link to create new item using Cdialog widget.
<?php $cs = Yii::app()->getClientScript();
$cs->registerCoreScript("jquery");
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'enableAjaxValidation'=>false,
)); ?>
<div class="row">
<?php
echo $form->labelEx($model,'uname'); ?>
<?php echo $form->dropDownList($model,'uname',$model- >getUniversityList(),array('onchange'=>'getSchemes(this.value)','empty'=>'Select university')); ?>
<?php echo $form->error($model,'uname'); ?>
<?php //create university dialoge box
if(!Yii::app()->user->isGuest)
{
echo CHtml::ajaxLink('create new university',array('university/dialoge'),array(
'success'=>'js:function(data){
$("#createUniversity").dialog("open");
document.getElementById("create_university").innerHTML=data;
}'));
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'createUniversity',
'options'=>array(
'title'=>'Create University',
'autoOpen'=>false,
'modal'=>'true',
'width'=>'auto',
'height'=>'auto',
),
));
echo "<div id='create_university'></div>";
$this->endWidget('zii.widgets.jui.CJuiDialog');
}
?>
<div id="scheme">
</div>
</div>
<?php $this->endWidget(); ?>
</div>
<input type="hidden" id="url" value="<?php echo $this->createUrl('scheme/test'); ?>">
this works pretty good.
here is the javascript code for loading next dropdown in the same view file
<script type="text/javascript">
function getSchemes(uid)
{
if(uid==""){
document.getElementById("scheme").innerHTML='';
return;
}
jQuery(function($){
var url=document.getElementById("url").value;
$.post(url, { uid:uid },
function(data){
document.getElementById("scheme").innerHTML=data;
document.getElementById("scheme_link").style.display="block";
});
});
}
The scheme drop down is loaded as the scheme view code is
<?php $cs = Yii::app()->getClientScript();
$cs->registerCoreScript("jquery");
?>
<?php
echo "<div class=".'label'."><label for=".'sch'.">Scheme</label></div>";
echo "<select id=".'sch'." onchange='getDepartments(this.value);'>";
echo "<option value=".''.">"."Select Scheme</option>";
foreach($schemes as $s)
{
echo "<option value='".$s->schemeid."' >".$s->scheme_name."</option>";
}
echo "</select>";
?>
<?php
if(!Yii::app()->user->isGuest)
{
echo CHtml::ajaxLink('create new Scheme',array('scheme/dialoge','id'=>5),array(
'success'=>'js:function(data1){
$("#createScheme").dialog("open");
document.getElementById("create_scheme").innerHTML=data;
}'));?>
<?php
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'createScheme',
'options'=>array(
'title'=>'Create Scheme',
'autoOpen'=>false,
'modal'=>'true',
'width'=>'auto',
'height'=>'auto',
),
));
echo "<div id='create_scheme'></div>";
$this->endWidget('zii.widgets.jui.CJuiDialog');
}
?>
<div id="department">
</div>
<input type="hidden" id="urldepart" value="<?php echo $this->createUrl('department/test'); ?> ">
the second ajaxLink is shown as create new scheme but on clicking the link it shows the old create university dialog box instead of create scheme.
The simplest solution for this is to create the ID of the element that is causing problems as random.
Try adding:
'id' => 'some-element'.uniqid() // avoid mutliple ajax request because of using live
in the $htmlOptions array of ajaxLink