I have a sidebar that displays the 20 latest posts, what I’d really like to do is Ajaxify that loop so there’s a load more button at the bottom.
The problem is, it’s a fairly complicated loop and getting WordPress to work properly with Ajax is not childs play.
I’m fairly familiar with jQuery but I’m no expert when it comes to complicated server side stuff.
I’ve been reading about Ajax and WordPress for days now and I can’t get anything to work properly, or at all.
I tried this: How can I fetch loop of post titles via AJAX?
And it didn’t work, gave me a server error.
Here’s my little loop.
Even if I could just see how to output the post titles, ignoring all the other stuff with an Ajax request I’m sure I could hack away at it from there.
I just can’t get it to work, at all.
<ul>
<?php
$sidebar_query = new WP_Query(array(
'showposts' => 20
) );
?>
<?php while ($sidebar_query->have_posts()) : $sidebar_query->the_post(); ?>
<li>
<?php if(has_post_thumbnail()) :?>
<div class="figure">
<?php the_post_thumbnail('sidethumb'); ?>
</div> <!-- end div figure //centers thumbnail -->
<?php else :?>
<?php endif;?>
<a href="https://wordpress.stackexchange.com/questions/94080/<?php the_permalink() ?>">
<span class="theparentcat">
<?php
$cat_names = wp_list_pluck( get_the_category(), 'cat_name');
echo wp_sprintf_l( '%l', $cat_names );
?>
</span>
<h2><?php the_title (); ?></h2>
<span class="thetime">
<?php echo human_time_diff( get_the_time('U'), current_time('timestamp') ) . ' ago'; ?>
</span>
</a>
</li>
<?php endwhile; wp_reset_query(); ?>
</ul>
What is the script for you posted here? I hope it is not the script that will be called by the ajax request, isn’t it??
Normally a php script for an ajax request looks like this:
<?php
$output = array();
$posts = new WP_Query( array( 'showposts' => 20 ) );
foreach ( $posts as $post ) {
array_push( $output, $post->title );
}
header( 'Content-type: application/json' );
die( json_encode( $output ) );
In your JavaScript you retrive the json encoded data, decode them and print them out with JavaScript. If you need to access WordPress functions, you can use output buffering.
<?php
$output = array();
$posts = new WP_Query( array( 'showposts' => 20 ) );
foreach ( $posts as $post ) {
array_push( $output, $post->title );
}
header( 'Content-type: application/json' );
die( json_encode( $output ) );
Now you can access the data in your JS:
$.post(
adminurl,
data,
function( response ) {
$('#outputdiv').apend('<ul id="outputlist"></ul>');
for( var elem in response ) {
$('#outputlist').append('<li>' + response[elem] + '</li>');
}
}
);
If you need some WordPress functions, you can also use outputbuffering:
<?php
$output="";
$posts = new WP_Query( array( 'showposts' => 20 ) );
ob_start();
echo '<ul>';
foreach ( $posts as $post ) {
printf( '<li><a href="https://wordpress.stackexchange.com/questions/94080/%s">%s</a></li>', get_permalink( $post->ID ), $post->title );
}
echo '</ul>';
$output = ob_get_clean();
header( 'Content-type: application/json' );
die( json_encode( array( 'output' => $output ) ) );
And print out the whole bunch of data:
$.post(
adminurl,
data,
function( response ) {
$('#outputdiv').apend(response.output);
}
);
But it is always a very good idea to reduce the amount of data transfered by an ajax request. So it’s better only to return the plain post data and not the html.
Your scripts could look like this (untested!)
PHP:
<?php
$posts = new WP_Query( array( 'showposts' => 20 ) );
$data = array();
foreach ( $posts as $post ) {
$element = array(
'thumbnail' => '',
'permalink' => '',
'catlist' => '',
'title' => '',
'time' => '',
);
if ( has_post_thumbnail( $post->ID ) )
$element['thumbnail'] = get_the_post_thumbnail( $post->ID, 'sidethumb' );
ob_start();
echo wp_sprintf_l(
'%l',
wp_list_pluck( get_the_category( $post->ID ), 'cat_name')
);
$element['catlist'] = ob_get_clean();
ob_start();
echo human_time_diff( get_the_time('U'), current_time('timestamp') ) . ' ago';
$element['time'] = ob_get_clean();
$element['permalink'] = esc_attr( get_permalink( $post->ID ) );
$element['title'] = esc_html( $post->title );
array_push( $data, $element );
}
wp_reset_query();
header( 'Content-type: application/json' );
die( json_encode( $data ) );
JS:
var data = {};
$.post(
adminurl,
data,
function( response ) { printSidebarPosts(response); }
);
function printSidebarPosts( response ) {
var content="";
for ( var i in response ) {
var out = response[i];
var thumbdiv = ( out.thumbnail != '' ) ? '<div class="figure">%thumbnail%</div>' : '';
var elem =
'<li>%thumbdiv%'+
'<a href="https://wordpress.stackexchange.com/questions/94080/%permalink%">'+
'<span class="theparentcat">%catlist%</span>'+
'<h2>%title%</h2>'+
'<span class="thetime">%time%</span>'+
'</a></li>'
.replace( /%thumbdiv%/g, thumbdiv )
.replace( /%permalink%/g, out.permalink )
.replace( /%catlist%/g, out.catlist )
.replace( /%title%/g, out.title )
.replace( /%time%/g, out.time );
content = content + elem;
}
var sidebarcontent="<ul>%content%</ul>".replace( /%content%/g, content );
$('#sidebar').html( sidebarcontent );
}
In the PHP part you should only collect the data. And in the JavaScript part, create the HTML. This reduce the amount of transferred data a lot and speed up the ajax request.
UPDATE
Adding the low level basics, requested in the comments.
But how do I place a button that can be clicked…
<input type="button" id="get_more_posts_ajax_trigger" value="Show more posts" />
<a href="#" id="get_more_posts_ajax_trigger">Show more posts</a>
<div id="get_more_posts_ajax_trigger">Show more posts</div>
That’s three possible elements to display something you can click on. In your JavaScript you have to catch this click.
jQuery(document).ready(
function($){
$('#get_more_posts_ajax_trigger').click(
function(){
var data = {
'action' : [the ajax hook you registered in WordPress with add_action( 'wp_ajax_[action]', ... ) and add_action( 'wp_ajax_nopriv_[action]', ...)]
};
$.post( adminurl, data, function(response) { [see codeexamples above] } );
};
);
);
And by the way, that php being on my page COMPLETELY screws up may layout
You put the PHP code into your page? OK. You have to put it into a function. And you have to register this function as ajax-callback in WordPress. Use add_action( 'wp_ajax_[action]', 'YourFunctionNameHere' );
and add_action( 'wp_ajax_nopriv_[action]', 'YourFunctionNameHere' );
You have to read this Codex page about ajax and this Codex page about how to implement ajax in plugins. Especially the part Ajax on the Viewer-Facing Side.