Ajax category post loader - php

I have a working AJAX post loader, but I can't get it working on the category page. What am I doing wrong? I think I'm not getting categories correctly?
The category.php code:
<div id="ajaxCatPosts" class="cat-post-side left small-12 large-9">
<?php
while ( have_posts() ) : the_post();
include(__DIR__.'/views/cat-post-thumb.php');
endwhile;
?>
<div class="load-button">
<button id="more_cat_posts">Veel uudiseid</button>
</div>
</div>
The functions.php code:
function more_post_ajax(){
$ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 16;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
header("Content-Type: text/html");
$args = array(
'suppress_filters' => true,
'posts_per_page' => $ppp,
'paged' => $page,
);
$loop = new WP_Query($args);
if ($loop -> have_posts()) : while ($loop -> have_posts()) : $loop -> the_post();
include(__DIR__.'/views/cat-post-thumb.php');
endwhile;
endif;
wp_reset_postdata();
die($out);
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
And here is loadmore.js:
$(function() {
var ppp = 16; // Post per page
var pageNumber = 1;
function load_posts(){
pageNumber++;
var str = '&pageNumber=' + pageNumber + '&ppp' + ppp + '&action=more_post_ajax';
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append($data);
$("#more_posts").attr("disabled",false);
} else{
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
$('#more_posts').unbind('click');
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
load_posts();
});
});

To make it work more dynamically with any taxonomy or combinations of taxonomies so this solutions would work not only in category.php but in any other case. For example JS could pass taxonomy term arguments where to fetch pposts from.
So first in your AJAX call we need to pass in the term where we want to load our posts from, lets say category is named milk. (And also lets make POST arguments more readable)
function load_posts(){
pageNumber++;
var str = {
pageNumber: pageNumber,
ppp: ppp,
term: 'milk',
action: 'more_post_ajax'
};
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append($data);
$("#more_posts").attr("disabled",false);
} else{
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
In your PHP code
function more_post_ajax(){
$ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 16;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
$term = isset($_POST['term']) ? $_POST['term'] : 0;
header("Content-Type: text/html");
$args = array(
'suppress_filters' => true,
'posts_per_page' => $ppp,
'paged' => $page,
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'slug', // Depends whether JS passes you slug or ID of taxonomy term, in our case it is a slug
'terms' => array( $term ),
)
),
);
$loop = new WP_Query($args);
if ($loop -> have_posts()) : while ($loop -> have_posts()) : $loop -> the_post();
include(__DIR__.'/views/cat-post-thumb.php');
endwhile;
endif;
wp_reset_postdata();
die();
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
Your WP_Query is now hardcoded to search from category taxonomy where posts have terms that match with the queried ones. You could change it to whatever you want, your not stuck with category taxonomy only if you change tax_query in your arguments. To be more secure you might want to check if that term exists in that taxonomy first.

The answer to your question seems to be in the documentation here.
Specifically, before making the call to WP_Query you need to specify the category you want. You're currently setting up the query here:
$args = array(
'suppress_filters' => true,
'posts_per_page' => $ppp,
'paged' => $page,
);
And you'll need to extend that to this:
$args = array(
'category_name' => $category
'suppress_filters' => true,
'posts_per_page' => $ppp,
'paged' => $page,
);
This means that your AJAX call will need to include the category you want (`$category) in the JSON, or you'll have to extract it from the page url. One way you could do this is:
$args = array(
'suppress_filters' => true,
'posts_per_page' => $ppp,
'paged' => $page,
);
if (isset($_POST["category"]){
$args['category_name'] = $_POST["category"];
}
Correspondingly, you'd need to update your AJAX call to have a category element:
var str = '&pageNumber=' + pageNumber + '&ppp' + ppp + '&action=more_post_ajax' + '&category=milk';

Related

AJAX: 400 bad request

I have been searching for a couple days now for a solution but all threads related to a 400 bad request using AJAX seem to not be relevant to my issue or perhaps I am just missing it.
I made a page that lists the subcategories of a master category. This part works great. When a user clicks on a category, I need to use AJAX to retrieve all of the products associated with the category that the user just clicked.
page_template.php
<script type="text/javascript">
jQuery(function($) {
$('.seamBuilder_trigger').click(function() {
var catID = $(this).attr('id');
console.log(catID);
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php');?>',
dataType: "html", // add data type
data: {
action : 'get_products'
},
success: function(response) {
console.log(response);
$('.posts-area').html(response);
}
});
return false;
});
});
</script>
<section id="content" class="site-content">
<div id="seam-builder-wrap" class="container">
<?php
$masterCat = 39; // Master category 'Seam Builder' ID is 39)
$taxonomyName = "product_cat";
$termchildren = get_term_children($masterCat, $taxonomyName);
foreach ($termchildren as $child) {
$subCat = get_term_by('id', $child, $taxonomyName); //assigns $subCat to the current subcategory in the loop
$subCat_title = $subCat->name; //gets the name of the subcategory
$cat_id = $subCat->term_id; //gets the ID of the subcategory on its own
$thumbnail_id = get_term_meta($child, 'thumbnail_id', true); //gets the thumbnail of the subcategory
$image = wp_get_attachment_url($thumbnail_id); //gets the URL of the thumbnail
?>
<a id="<?php echo $cat_id ?>" class="seamBuilder_trigger" href="#">
<img src="<?php echo $image ?>" />
<span><?php echo $subCat_title ?></span>
</a>
<?php } //ends for foreach loop above ?>
</div>
<div class="posts-area">
</div>
</section>
functions.php
<?php
function get_products() {
$cat_id = (isset($_POST['cat'])) ? $_POST['cat'] : '';
echo 'hello there' . $cat_id;
// Query Arguments
$args = array(
'cat' => $cat_id,
'post_type' => array('products'),
'post_status' => array('publish'),
'posts_per_page' => -1,
);
// The Query
$ajaxposts = new WP_Query($args);
$output = '';
if ($ajaxposts -> have_posts()) : while ($ajaxposts -> have_posts()) : $ajaxposts -> the_post();
$output .= 'div class="seamBuilderRow">';
$output .= $cat_id;
$output .= '</div>';
endwhile;
endif;
wp_reset_postdata();
wp_die();
}
// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_products');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_products');
?>
I get 400 bad request as soon as I click on one of my categories that should fire AJAX. Any ideas?
Your action hook handler is wp_ajax_get_ajax_posts (and wp_ajax_nopriv_get_ajax_posts), hence the action parameter should be get_ajax_posts as well. Since it's not, WordPress responds to your AJAX call with a 400 Bad Request status.
This should work:
$.ajax({
type: 'POST',
url: '<?php echo admin_url('admin-ajax.php');?>',
dataType: "html", // add data type
data: {
action : 'get_ajax_posts'
},
success: function(response) {
console.log(response);
$('.posts-area').html(response);
}
});

Display "Show Less" button when AJAX has no more posts to show

I have an AJAX "show more posts" script running on my WordPress page.
The only thing is when I click "show more" and reach the end, I would like for the button to change and say "show less" then close all of the AJAX that was shown.
How could I alter my current script to do that?
Below is the code
<div id="work" class="case-studies">
<h2>
Case studies
</h2>
<div class="case-study-squares">
<div id="ajax-posts" class="row">
<?php
$args = array(
'post_type' => 'casestudies',
'post_status' => 'publish',
);
$casestudies = new WP_Query( $args );
if( $casestudies->have_posts() ) :
?>
<?php
$postsPerPage = 4;
$args = array(
'post_type' => 'casestudies',
'posts_per_page' => $postsPerPage,
'cat' => 0
);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
?>
<div class="case-open-container">
<div class="case-toggle"><?php the_post_thumbnail('large'); ?><h3><?php echo
the_title(); ?></h3></div>
</div>
<?php
endwhile;
wp_reset_postdata();
?>
</div>
<?php
else :
esc_html_e( 'No case studies posted yet!', 'text-domain' );
endif;
?>
</div>
</div>
<div id="more_posts" class="view-more">
<h3>
View more work
</h3><p class="down-arrow">
▼
</p>
</div>
Below code is from my functions file
wp_enqueue_script( 'custom_js', get_template_directory_uri(). '/js/custom.js', array( 'jquery'), '', true ); wp_localize_script( 'custom_js', 'ajax_posts', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'noposts' => __('No older posts found', 'enzyme-communications'), ));
function more_post_ajax(){
$ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 4;
$page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;
header("Content-Type: text/html");
$args = array(
'suppress_filters' => true,
'post_type' => 'casestudies',
'posts_per_page' => $ppp,
'cat' => 0,
'paged' => $page,
);
$loop = new WP_Query($args);
$rows = get_field('repeater_field_name');
if($rows)
{ $image = get_sub_field('image'); }
$out = '';
if ($loop -> have_posts()) : while ($loop -> have_posts()) : $loop -> .
the_post();
$out .= ' <div class="case-more-container">
<div class="case-more-toggle"><img src="'.get_the_post_thumbnail_url().'"> .
<h3>'.get_the_title().'</h3></div>
</div>
';
endwhile;
endif;
wp_reset_postdata();
die($out);
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');
Below is the custom.js that also relates to this
$(document).ready(function(){
var ppp = 4; // Post per page
var cat = 0;
var pageNumber = 1;
function load_posts(){
pageNumber++;
var str = '&cat=' + cat + '&pageNumber=' + pageNumber + '&ppp=' + ppp +
'&action=more_post_ajax';
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append($data);
$("#more_posts").attr("disabled",false);
} else{
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
load_posts();
});
});
Really appreciate any help given in advance :)
I hope this would help you!
Try this out
$(document).ready(function(){
var ppp = 4; // Post per page
var cat = 0;
var pageNumber = 1;
$("#more_posts").text("Show More");
function load_posts(){
pageNumber++;
var str = '&cat=' + cat + '&pageNumber=' + pageNumber + '&ppp=' + ppp +
'&action=more_post_ajax';
$.ajax({
type: "POST",
dataType: "html",
url: ajax_posts.ajaxurl,
data: str,
success: function(data){
var $data = $(data);
if($data.length){
$("#ajax-posts").append("<div id='ajax-posts-'" + pageNumber + ">" + $data + "</div>");
$("#more_posts").text("Show More");
$("#more_posts").attr("disabled",false);
} else{
//If there are no more posts
$("#more_posts").text("Show Less");
$("#more_posts").attr("disabled",true);
}
},
error : function(jqXHR, textStatus, errorThrown) {
$loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
return false;
}
function less_posts(){
$("#ajax-posts-" + pageNumber).remove();
pageNumber--;
}
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
if($("#more_posts").text == "Show More")
{
load_posts();
}
else if($("#more_posts").text == "Show Less")
{
less_posts();
}
});
});
Thank you ;)
I don't know, How your code works , but my script helps to change the text.
check this and try with your code, hope this will help you.
jQuery(document).ready(function(){
jQuery("#more_posts").on("click",function(){ // When btn is pressed.
jQuery(this).toggleClass("less_show");
if(jQuery(this).hasClass("less_show")){
jQuery("#more_posts h3").text('View less work ');
}
else{
jQuery("#more_posts h3").text('View more work ');
}
});
});

Wordpress admin-ajax.php 400

I have a strange and frustrating behaviour of wordpress admin-ajax.php file, when i make an ajax request it returns 400 error bad request.
var ajaxurl = '<?php echo site_url() ?>/wp-admin/admin-ajax.php';
var true_posts = '<?php echo serialize($wp_query->query_vars); ?>';
var current_page = <?php echo (get_query_var('paged')) ? get_query_var('paged') : 1; ?>;
var max_pages = '<?php echo $wp_query->max_num_pages; ?>';
jQuery(function($){
$('#true_loadmore').click(function(){
$(this).text('Loading...');
var data = {
'action': 'loadmore',
'query': true_posts,
'page' : current_page
};
$.ajax({
url:ajaxurl,
data:data,
type:'POST',
success:function(data){
if( data ) {
$('#true_loadmore').text('View more recent Posts').before(data);
current_page++;
if (current_page == max_pages) $("#true_loadmore").remove();
} else {
$('#true_loadmore').remove();
}
}
});
});
});
my functions.php .
add_action('wp_ajax_loadmore', 'true_load_posts');
add_action('wp_ajax_nopriv_loadmore', 'true_load_posts');
function true_load_posts(){
$args = unserialize( stripslashes( $_POST['query'] ) );
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
query_posts( $args );
if( have_posts() ) :
while( have_posts() ): the_post();
get_template_part( 'template-parts/post/content', get_post_format() );
endwhile;
endif;
die();
}
And I got 400 error .
Someone could help me to please? thank you.
the problem should be the action in your sending data.
The 'action' value must correspond to the function name in the php side (and in the add_action method ).
var data = {
'action': 'true_load_posts', //instead of 'loadmore'
'query': true_posts,
'page' : current_page
};
Hope this help.

Query posts via ajax with select element

So I have select element with 3 options: men, women, unisex. Whenever a user selects a new option, the posts should reload. I now have this as ajax function:
$(document).ready(function () {
$('#select-gender').change(function(){
$.ajax({
url: ajaxurl + "/woocommerce/archive-content.php",
type: "post",
data: {option: $(this).find("option:selected").val()},
success: function(data){
//adds the echoed response to our container
$("#topdog").html(data);
}
});
});
});
And this is the archive-content.php file:
<?php
function details($opt) {
echo 'option: ' . $opt;
}
details($_POST['option']);
$selected = $_POST['option'];
// The Query
$the_query = new WP_Query( $args );
$args=array(
'gender' => $selected,
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1
);
$my_query = null;
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
echo 'List of manly product';
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p><?php the_title(); ?></p>
<?php
endwhile;
}
wp_reset_query(); // Restore global post data stomped by the_post().
?>
I realise now that just changing the $selected variable does not reload my posts. Should I load my posts in the 'data' part of the ajax function? How would I do that?
Thanks!

How to implement pagination on a custom WP_Query Ajax

I want to paginate my WordPress posts in a custom loop with Ajax, so when I click on load more button posts will appear.
My code:
<?php
$postsPerPage = 3;
$args = array(
'post_type' => 'post',
'posts_per_page' => $postsPerPage,
'cat' => 1
);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
?>
<h1><?php the_title(); ?></h1>
<p>
<?php the_content(); ?>
</p>
<?php
endwhile;
echo 'Load More';
wp_reset_postdata();
?>
This code does not paginate. Is there a better way to do this?
The Load More button needs to send a ajax request to the server and the returned data can be added to the existent content using jQuery or plain javascript. Assuming your using jQuery this would starter code.
Custom Ajax Handler (Client-side)
Load More
Change to:
<a id="more_posts" href="#">Load More</a>
Javascript: - Put this at the bottom of the file.
//</script type="text/javascript">
var ajaxUrl = "<?php echo admin_url('admin-ajax.php')?>";
var page = 1; // What page we are on.
var ppp = 3; // Post per page
$("#more_posts").on("click",function(){ // When btn is pressed.
$("#more_posts").attr("disabled",true); // Disable the button, temp.
$.post(ajaxUrl, {
action:"more_post_ajax",
offset: (page * ppp) + 1,
ppp: ppp
}).success(function(posts){
page++;
$(".name_of_posts_class").append(posts); // CHANGE THIS!
$("#more_posts").attr("disabled",false);
});
});
//</script>
Custom Ajax Handler (Server-side)
PHP - Put this in the functions.php file.
function more_post_ajax(){
$offset = $_POST["offset"];
$ppp = $_POST["ppp"];
header("Content-Type: text/html");
$args = array(
'post_type' => 'post',
'posts_per_page' => $ppp,
'cat' => 1,
'offset' => $offset,
);
$loop = new WP_Query($args);
while ($loop->have_posts()) { $loop->the_post();
the_content();
}
exit;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

Categories