0

We have a custom post type named accommodation and it has one taxonomy, named accommodation_city. Its children are 4 terms, simple city names.

What I have done so far, is make 2 queries:

  1. Will show the 4 city names horizontaly
  2. Will show ALL the posts that are included in these 4 terms.
$terms = get_terms('accommodation_city'); ?>
<ul class="cat-list">
  <li><a class="cat-list_item active" href="#!" data-slug="">All cities</a></li>
  <?php foreach($terms as $term) : ?>
    <li>
      <a class="cat-list_item" href="#!" data-slug="<?= $term->slug; ?>">
        <?= $term->name; ?>
      </a>
    </li>
  <?php endforeach; ?>
</ul>

The code abobe will simply show the 1st query.

  $accs = new WP_Query([
    'post_type' => 'accommodation',
    'posts_per_page' => 2,
    'order_by' => 'date',
    'order' => 'desc',
    'tax_query' => array(
      array(
        'taxonomy' => 'accommodation_city',
        'field' => 'slug',
        'operator' => 'EXISTS'
      )
    )
  ]);

  if ($accs->have_posts()): ?>
    <ul class="project-tiles">
      <?php
      while($accs->have_posts()) : $accs->the_post();
        echo get_the_title() . "<br>";
      endwhile;
      ?>
    </ul>
    <?php wp_reset_postdata();
  endif;

The code above will simply show the 2nd query, but limiting the results to 2 posts.

Now we go to the part where we create some Javascript, in order to make our AJAX call.

jQuery('.cat-list_item').on('click', function() {

  jQuery('.cat-list_item').removeClass('active');
  jQuery(this).addClass('active');

  jQuery.ajax({
    type: 'POST',
    url: '/wp-admin/admin-ajax.php',
    dataType: 'html',
    data: {
      action: 'filter_projects',
      category: jQuery(this).data('slug'),
    },
    success: function(res) {
      jQuery('.project-tiles').html(res);
    }
  })
});

Our goal here is to show 4 cities and then everytime we click on one city name, to show it's posts that are related to that term.

The code to do that is below:

function filter_projects() {
  $catSlug = $_POST['category'];

  if ($catSlug){
    $ajaxposts = new WP_Query([
      'post_type' => 'accommodation',
      'posts_per_page' => 2,
      'orderby' => 'menu_order',
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => 'accommodation_city',
          'field' => 'slug',
          'terms' => $catSlug,
        )
      )
    ]);
  } else {
    $ajaxposts = new WP_Query([
      'post_type' => 'accommodation',
      'posts_per_page' => 2,
      'orderby' => 'menu_order',
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => 'accommodation_city',
          'field' => 'slug',
          'operator' => 'EXISTS'
        )
      )
    ]);
  }

  $response = '';

  if($ajaxposts->have_posts()) {
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
      $response .= get_the_title() . "<br>";
    endwhile;
  } else {
    $response = 'empty';
  }

  echo $response;
  exit;
}
add_action('wp_ajax_filter_projects', 'filter_projects');
add_action('wp_ajax_nopriv_filter_projects', 'filter_projects');

How can I add "Load more" functionality to the code above? Is it doable? Should I replace my code to REST API in order to do something like that?

1 Answer 1

0

This is all the code to also add "load more" functionality:

/*
  Widget name  : Filtering (accommodation)
  Parameters  : 'cpt'
  Function   : filtering()
*/
function filtering($filtering){

  $taxon = get_object_taxonomies($filtering['cpt']);
  $terms = get_terms($taxon[0]);

  $accs = new WP_Query([
    'post_type' => $filtering['cpt'],
    'posts_per_page' => 6,
    'order_by' => 'date',
    'order' => 'desc',
    'tax_query' => array(
      array(
        'taxonomy' => $taxon[0],
        'field' => 'slug',
        'operator' => 'EXISTS'
      )
    )
  ]);
  $found = $accs->found_posts;
  ?>

  <div class="filtering x-9">
    <div class="filtering-cpt">
      <a class="filtering-cpt-sin active" href="#!" data-load="<?php echo $found; ?>" data-type="<?php echo $filtering['cpt']; ?>" data-slug=""><?php _e('All','xlate'); ?></a>
      <?php foreach($terms as $term) : ?>
      <a class="filtering-cpt-sin" href="#!" data-load="<?php echo $term->count; ?>" data-type="<?php echo $filtering['cpt']; ?>" data-slug="<?php echo $term->slug; ?>"><?php echo $term->name; ?></a>
      <?php endforeach; ?>
    </div>

    <?php

    if ($accs->have_posts()): ?>
      <div class="filtering-res x-9">
        <?php while($accs->have_posts()) : $accs->the_post(); ?>
        <div class="filtering-res-sin x-3">
          <div class="filtering-res-sin-top">
            <?php
            $image_data = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), "large" );
            $get_map_link = get_post_custom_values($key = 'map');
            ?>
            <img src="<?php echo $image_data[0]; ?>" width="<?php echo $image_data[1]; ?>" height="<?php echo $image_data[2]; ?>" alt="<?php echo get_the_title(); ?>" />
          </div>
          <div class="filtering-res-sin-bot darkbg cropit xx-anim">
            <div class="filtering-res-sin-bot-tit"><?php echo get_the_title(); ?></div>
            <div class="filtering-res-sin-bot-bar"></div>
            <div class="filtering-res-sin-bot-tog">Contact information <img src="https://lgkm.aero/wp-content/uploads/2022/11/load-more-plus-white-14x14-1-1.svg" width="12" height="12" alt="+" /></div>
            <div class="filtering-res-sin-bot-con"><?php echo get_the_content(); ?></div>
            <a class="filtering-res-sin-bot-but" href="<?php echo (($get_map_link != '') ? $get_map_link[0] : ''); ?>"><img src="https://lgkm.aero/wp-content/uploads/2022/11/find-on-map-white-26x34-1.svg" width="26" height="34" alt="|" /> Find on map</a>
          </div>
        </div>
        <?php endwhile; ?>
      </div>
      <div class="filtering-load x-12" data-load="<?php echo $found; ?>" data-type="<?php echo $filtering['cpt']; ?>" data-slug="">Load more <img src="https://lgkm.aero/wp-content/uploads/2022/11/shop-plus-20x20-1.svg" width="14" height="14" alt="+" /></div>
      <?php wp_reset_postdata();
    endif; ?>
  </div>

<?php }

function filtering_ajax() {

  $catCpt = $_POST['type'];
  $terms = get_object_taxonomies($catCpt);
  $catSlug = $_POST['category'];

  if ($catSlug){
    $ajaxposts = new WP_Query([
      'post_type' => $catCpt,
      'posts_per_page' => 3,
      'orderby' => 'date',
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => $terms[0],
          'field' => 'slug',
          'terms' => $catSlug,
        )
      )
    ]);
  } else {
    $ajaxposts = new WP_Query([
      'post_type' => $catCpt,
      'posts_per_page' => 3,
      'orderby' => 'date',
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => $terms[0],
          'field' => 'slug',
          'operator' => 'EXISTS'
        )
      )
    ]);
  }

  $found = $ajaxposts->found_posts;
  $response = '';

  if($ajaxposts->have_posts()) {
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
      $image_data = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), "large" );
      $get_map_link = get_post_custom_values($key = 'map');
      $response .= '
      <div class="filtering-res-sin x-3">
        <div class="filtering-res-sin-top">
          <img src="' . $image_data[0] . '" width="' . $image_data[1] . '" height="' . $image_data[2] . '" alt="' . get_the_title() . '" />
        </div>
        <div class="filtering-res-sin-bot darkbg cropit vsb xx-anim">
          <div class="filtering-res-sin-bot-tit">' . get_the_title() . '</div>
          <div class="filtering-res-sin-bot-bar"></div>
          <div class="filtering-res-sin-bot-tog">Contact information <img src="https://lgkm.aero/wp-content/uploads/2022/11/load-more-plus-white-14x14-1-1.svg" width="12" height="12" alt="+" /></div>
          <div class="filtering-res-sin-bot-con">' . get_the_content() . '</div>
          <a class="filtering-res-sin-bot-but" href="' . (($get_map_link != '') ? $get_map_link[0] : '') . '"><img src="https://lgkm.aero/wp-content/uploads/2022/11/find-on-map-white-26x34-1.svg" width="26" height="34" alt="|" /> Find on map</a>
        </div>
      </div>';
    endwhile;
  } else {
    $response = '';
  }

  echo $response;
  exit;
}
add_action('wp_ajax_filtering_ajax', 'filtering_ajax');
add_action('wp_ajax_nopriv_filtering_ajax', 'filtering_ajax');



function filtering_ajax_load() {

  $catCpt = $_POST['type'];
  $terms = get_object_taxonomies($catCpt);
  $catOff = $_POST['offset'];
  $catSlug = $_POST['category'];

  if ($catSlug){
    $ajaxposts = new WP_Query([
      'post_type' => $catCpt,
      'posts_per_page' => 3,
      'offset' => $catOff,
      'orderby' => 'date',
      'paged' => 1,
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => $terms[0],
          'field' => 'slug',
          'terms' => $catSlug,
        )
      )
    ]);
  } else {
    $ajaxposts = new WP_Query([
      'post_type' => $catCpt,
      'posts_per_page' => 3,
      'offset' => $catOff,
      'orderby' => 'date',
      'paged' => 1,
      'order' => 'desc',
      'tax_query' => array(
        array(
          'taxonomy' => $terms[0],
          'field' => 'slug',
          'operator' => 'EXISTS'
        )
      )
    ]);
  }

  $response = '';

  if($ajaxposts->have_posts()) {
    while($ajaxposts->have_posts()) : $ajaxposts->the_post();
      $image_data = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), "large" );
      $get_map_link = get_post_custom_values($key = 'map');
      $response .= '
      <div class="filtering-res-sin x-3">
        <div class="filtering-res-sin-top">
          <img src="' . $image_data[0] . '" width="' . $image_data[1] . '" height="' . $image_data[2] . '" alt="' . get_the_title() . '" />
        </div>
        <div class="filtering-res-sin-bot darkbg cropit vsb xx-anim">
          <div class="filtering-res-sin-bot-tit">' . get_the_title() . '</div>
          <div class="filtering-res-sin-bot-bar"></div>
          <div class="filtering-res-sin-bot-tog">Contact information <img src="https://lgkm.aero/wp-content/uploads/2022/11/load-more-plus-white-14x14-1-1.svg" width="12" height="12" alt="+" /></div>
          <div class="filtering-res-sin-bot-con">' . get_the_content() . '</div>
          <a class="filtering-res-sin-bot-but" href="' . (($get_map_link != '') ? $get_map_link[0] : '') . '"><img src="https://lgkm.aero/wp-content/uploads/2022/11/find-on-map-white-26x34-1.svg" width="26" height="34" alt="|" /> Find on map</a>
        </div>
      </div>';
    endwhile;

  } else {
    $response = ''; ?>
  <?php }

  echo $response;
  exit;
}
add_action('wp_ajax_filtering_ajax_load', 'filtering_ajax_load');
add_action('wp_ajax_nopriv_filtering_ajax_load', 'filtering_ajax_load');

Then the JS part:

<script>
jQuery('.filtering .filtering-cpt-sin').on('click', function() {

  jQuery('.filtering .filtering-cpt-sin').removeClass('active');
    jQuery('.filtering-load').removeClass('dis');
  jQuery(this).addClass('active');

    jQuery('.filtering-load').attr('data-type',jQuery(this).attr('data-type'));
    jQuery('.filtering-load').attr('data-slug',jQuery(this).attr('data-slug'));
    jQuery('.filtering-load').attr('data-load',jQuery(this).attr('data-load'));

  jQuery.ajax({
    type: 'POST',
    url: '/wp-admin/admin-ajax.php',
    dataType: 'html',
    data: {
            type: jQuery(this).attr('data-type'),
            offset: 0,
      action: 'filtering_ajax',
      category: jQuery(this).attr('data-slug')
    },
    success: function(res) {
      jQuery('.filtering .filtering-res').html(res);
    }
  })
});

jQuery('.filtering .filtering-load').on('click', function() {
    jQuery.ajax({
    type: 'POST',
    url: '/wp-admin/admin-ajax.php',
    dataType: 'html',
    data: {
            type: jQuery(this).attr('data-type'),
            offset: jQuery('.filtering-res-sin').length,
      action: 'filtering_ajax_load',
      category: jQuery(this).attr('data-slug')
    },
    success: function(res) {
      jQuery('.filtering .filtering-res').append(res);
            if (jQuery('.filtering-res-sin').length >= jQuery('.filtering-load').attr('data-load')){
                jQuery('.filtering-load').addClass('dis');
            }
    }
  })
});
</script>

Some CSS to make it pretty:

.filtering {display: flex;justify-content: center;flex-direction: column;align-items: center;gap: 50px 0;margin-right: auto;margin-left: calc( var(--grid) + var(--gutter) );}
.filtering-cpt {display: flex;gap: 0 20px;}
.filtering-cpt a {font-family: Averta;font-size: 21px;font-weight: 600;line-height: 20px;color:#979797;transition:color .3s;}
.filtering-cpt a.active {color:#000;}
.filtering-res {display: flex;flex-wrap: wrap;gap: calc(var(--gutter) * 2);counter-reset:count;}
.filtering-res-sin {display: flex;flex-direction: column;color:#fff;counter-increment:count;}
.filtering-res-sin a {color:#fff;}
.filtering-res-sin-top {display: flex;flex-direction: column;}
.filtering-res-sin-top img {aspect-ratio: 4/3;object-fit: cover;object-position: center;}
.filtering-res-sin-bot {padding: 42px 50px 42px 60px;display: flex;flex-direction: column;gap: 17px;position:relative}
.filtering-res-sin-bot::after {content:counter(count, decimal-leading-zero);position:absolute;left:20px;top:25px;color:#fff;font-family: Roboto;font-size: 15px;font-weight: 400;line-height: 21px;}
.filtering-res-sin-bot-tit {font-family: Averta;font-size: 24px;font-weight: 600;line-height: 29px;}
.filtering-res-sin-bot-bar {background-color:#474B56;width:100%;height:1px;}
.filtering-res-sin-bot-tog {font-family: Averta;font-size: 17px;font-weight: 600;line-height: 20px;display:flex;align-items:center;gap:0 7px;}
.filtering-res-sin-bot-but {font-family: Averta;font-size: 20px;font-weight: 600;line-height: 24px;display:flex;align-items:center;gap:0 13px;}
.filtering-load {display:flex;justify-content:center;gap:0 7px;cursor:pointer;font-family: Averta;font-size: 21px;font-weight: 600;line-height: 20px;}
.filtering-load.dis {opacity:0.4;cursor:not-allowed;}

And finally call the one function that does the trick:

$filtering = array('cpt' => 'accommodation');
filtering($filtering);

Just change the accommodation to your own custom post type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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