Load categories with ajax

The question:

I don’t have any link or demo to show cos I’m working locally

I have news posts with different categories.

I want to show the categories as buttons.

When you click a category I want to load those posts using ajax so I don’t have page reload.

The category buttons

    <ul>

      <?php

        $cat_args = array(
          'orderby'     => 'name',
          'order'       => 'ASC',
          'hide_empty'  => 1
        );


        $cats = get_categories($cat_args);

        foreach($cats as $cat){
          echo '<li><a href="#" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" data-slug="' . $cat->term_id . '" class="js-category-button">' . $cat->name . '</a></li>';
        }

        //echo '<pre>'; print_r($cats); echo '</pre>';

      ?>

     </ul>

The jQuery

    $('.js-category-button').on('click', function(e){
      e.preventDefault();
      var catID = $atj(this).data('slug');
      var ajaxurl = 'http://my-site.co.uk <?php bloginfo("wpurl");?>/wp-admin/admin-ajax.php';
        $atj.ajax({
            type: 'POST',
            url: ajaxurl,
            dataType: 'jsonp',
            crossDomain : true,
            data: {"action": "load-filter", cat: catID },
            success: function(response) {
                $atj(".the-news").html(response);
                return false;
            }
        });
    })       

The php query in functions.php

    add_action( 'wp_ajax_nopriv_load-filter', 'prefix_load_cat_posts' );
    add_action( 'wp_ajax_load-filter', 'prefix_load_cat_posts' );

    function prefix_load_cat_posts () {
      $cat_id = $_POST[ 'cat' ];

      $args = array (
        'cat' => $cat_id,
        'posts_per_page' => 3,
        'order' => 'DESC'
      );

      $posts = get_posts( $args );

      ob_start ();

      foreach ( $posts as $post ) {
        setup_postdata( $post ); ?>

        <div id="post-<?php echo $post->ID; ?> <?php post_class(); ?>">
          <h1 class="posttitle"><a href="<?php the_permalink(); ?>" rel="nofollow noreferrer noopener"><?php the_title(); ?></a></h1>

          <div id="post-content">
          <?php the_excerpt(); ?>
        </div>

        </div>

      <?php } wp_reset_postdata();

      $response = ob_get_contents();
      ob_end_clean();

      echo $response;

    }

The categories appear, when I click them the console gives me 502 Proxy Error ( The host was not found. )

Can anyone see what I’m doing wrong or how to fix this.

Update

I have the code partly working now but i still have problems

My js is currently in a separate js file

The only way I could get it work was using the site url for ajaxurl

  $atj('.js-category-button').on('click', function(e){
    e.preventDefault();
    var catID = $atj(this).data('slug');
    var ajaxurl = 'http://mysite.co.uk/wp-admin/admin-ajax.php';
      $atj.ajax({
          type: 'POST',
          url: ajaxurl,
          crossDomain : true,
          //dataType: 'jsonp',
          //contentType: "text/html",
          dataType: 'html',
          data: {"action": "load-filter", cat: catID },
          success: function(response) {
              $atj(".the-news").append(response);
              return false;
          }
      });
  })

My php script is in functions.php

I think there should only be one tag in functions.php so I didn’t want to break out of the php in the function to create the html markup. Thats why I’m trying to add it all to the $response variable that then gets echoed.

  add_action( 'wp_ajax_nopriv_load-filter', 'prefix_load_cat_posts' );
  add_action( 'wp_ajax_load-filter', 'prefix_load_cat_posts' );

  function prefix_load_cat_posts () {

    global $post;

    $cat_id = $_POST[ 'cat' ];

    $args = array (
      'cat' => $cat_id,
      'posts_per_page' => 3,
      'order' => 'ASC'
    );


    $cat_query = new WP_Query($args);

    if($cat_query->have_posts()) :
      while($cat_query->have_posts()) :
        $cat_query->the_post();


      $response = '<div class="the-post">';
      $response .= '<h1 class="the-title">';
      $response .= '<a href="#" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'. the_title() .'</a>';
      $response .= '</h1>';
      $response .= '<p>'. the_content().'</p>';
      $response .= '</div>';


      echo $response;

      endwhile; 

      endif; 

      wp_reset_postdata(); 

      die(1); 
  }    

This sort of works. I get html output with the title of the post but it’s outside the html and I can’t output the content.

  add_action( 'wp_ajax_nopriv_load-filter', 'prefix_load_cat_posts' );
  add_action( 'wp_ajax_load-filter', 'prefix_load_cat_posts' );

  function prefix_load_cat_posts () {

    global $post;

    $cat_id = $_POST[ 'cat' ];

    $args = array (
      'cat' => $cat_id,
      'posts_per_page' => 3,
      'order' => 'ASC'
    );


    $cat_query = new WP_Query($args);

    if($cat_query->have_posts()) :
      while($cat_query->have_posts()) :
        $cat_query->the_post();


      $response = '<div class="the-post">';
      $response .= '<h1 class="the-title">';
      $response .= '<a href="#" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'. the_title() .'</a>';
      $response .= '</h1>';
      $response .= '<p>'. the_content().'</p>';
      $response .= '</div>';


      echo $response;

      endwhile; 

      endif; 

      wp_reset_postdata(); 

      die(1); 
  }    

Any help getting this to work would be greatly appreciated.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

The error says it all, you are sending the request to a invalid host.

Change this:

 var ajaxurl = 'http://my-site.co.uk <?php bloginfo("wpurl");?>/wp-admin/admin-ajax.php';

To:

 var ajaxurl = "<?php echo esc_js( admin_url( 'admin-ajax.php' ) ) ?>";

Note: from your code and description I’m assuming you are generating the jQuery code within PHP and it is not in a js file.

Additionally, you must die/exit the program after after the ajax response is sent out (this is not done automatically and the request could be open forever, see documentation):

echo $response;
// Terminate
exit;

And more wrong things I see in your code: you are saying to jQuery to work with JSONP data but your ajax response is a HTML string. You should remove this line or change it to the correct data type:

dataType: 'jsonp',

After the edition of the question, you have introduced a new problem. You are trying to asign the_content() to the value of $response but the_content() prints the post content, it doesn’t return any value. If you want to get the value of the post content you should use get_the_content() instead and to get the same result as the_content you should apply the_content filters. Change this:

$response .= '<p>'. the_content().'</p>';

To:

// <p> are not need because the the_content filters include wpautop()
$response .= apply_filters( 'the_content', get_the_content() );


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment