Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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="<?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>
share|improve this question
2  
You should post the "server error". And, IMO, more important than the loop is the code you tried to adapt from that Q&A. I've made a second edit, props to @JohannesPille for cleaning up the code, but I couldn't determine "what is exactly your question", sometimes it's a simple matter of adding a question mark in people's Question, but I couldn't find anything in yours that is the question... Maybe this can be a starting point: How to Use Ajax in a WordPress Shortcode? –  brasofilo Apr 1 '13 at 3:12
    
Sorry for not making it more clear. My exact question would be "How do I add a button that users can click to load the next 20 posts with my loop via ajax?". I'm not quite sure what the exact error is from the link I posted, it just says HTTP Error 500 (Internal Server Error): An unexpected condition was encountered while the server was attempting to fulfill the request. When I paste the "function my_AJAX_more_links_function(){ etc" into my functions.php it just gives the above error, so the page never loads at all. –  andy Apr 1 '13 at 7:15

1 Answer 1

up vote 7 down vote accepted
+50

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="%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="%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.

share|improve this answer
    
Thanks for the long, detailed response, Ralf. But how do I place a button that can be clicked to run this? –  andy Apr 16 '13 at 10:57
    
And by the way, that php being on my page COMPLETELY screws up may layout, the output of other loops doesn't show up etc. –  andy Apr 16 '13 at 11:32
1  
@andy I'm fairly familiar with jQuery hmmm... you are familiar with jQuery and don't know how to do an ajax request or trigger an ajax event?? Really? OK, I update my answer and start at the basic. The low level basics I think. –  Ralf912 Apr 16 '13 at 13:53
    
Sorry for the delayed response, I've been ill the last few days. What do you mean by 'put into a function'? In my funtions.php or do I create a new file then add_action to register it in my functions file? –  andy Apr 17 '13 at 18:11
    
Sorry, this is not the place for absolute beginners. There are a lot of books, videos and tutorials out there. And finally: I'm not your personal trainer. –  Ralf912 Apr 17 '13 at 20:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.