I have a custom post type built in WordPress named Knowledge.
Knowledge currently only has 4 posts in total. By default, 3 posts are shown, then on load more click, I want the last, 4th blog card to show.
However, currently, my AJAX request isn't succeeding, it gives me the /wp-admin/admin-ajax.php 403 (Forbidden) error. Similar questions stated that it might be related to security plugins. However, I have disabled any security related plugins (Jetpack) and the error still exists.
Here is my approach so far:
knowledge-listing.php
<?php
global $post;
$args = array(
'post_type' => 'knowledge',
'posts_per_page' => 3,
'post_status' => 'publish',
'orderby' => 'publish_date',
'order' => 'DESC'
);
$query = new WP_Query($args);
if ($query->have_posts()):
while ($query->have_posts()):
$query->the_post();
get_part('templates/snippets/knowledge-card', array(
'heading' => get_the_title() ,
'subheading' => get_the_excerpt() ,
'background' => wp_get_attachment_url(get_post_thumbnail_id($post->ID)) ,
));
endwhile;
wp_reset_postdata(); ?>
<div class="knowledgeListing__loadmore">
<a href="#" id="loadmore" class="button--loadmore" data-type="knowledge" data-max-num-pages="<?php echo $query->max_num_pages; ?>">
<?php echo _e('Load More', 'theme'); ?>
</a>
</div>
<?php
endif; ?>
loadmore.js
jQuery(function($){
$(document).ready(function(){
$("#loadmore").on('click', function (e) {
e.preventDefault();
var btn = $(this);
showNextItems(btn);
});
function showNextItems(btn) {
var max_num_pages = btn.data('max-num-pages');
var post_type = btn.data('type');
var button = btn,
data = {
'action':'loadmore',
'query': loadmore_params.posts,
'page' : loadmore_params.current_page,
// 'security' : loadmore_params.security,
// 'max_num_pages' : max_num_pages,
// 'post_type' : post_type
};
$.ajax({
url : loadmore_params.ajaxurl,
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...');
},
success : function( data ){
if( data ) {
button.text( 'Load More' ).prev().before(data);
loadmore_params.current_page++;
$('.knowledgeListing__wrapper').find('.knowledgeCard').last().after( data );
if ( loadmore_params.current_page == max_num_pages ){
button.remove();
}
console.log("success");
} else {
button.remove();
}
},
error : function(error){
button.text( 'Load More' );
console.table("Data: " + data);
console.table("loadmore_params: " + loadmore_params);
// console.log(error);
}
});
}
});
});
The following two console.log's spit out [object Object]
console.table("Data: " + data);
console.table("loadmore_params: " + loadmore_params);
Unsure where things are going wrong?
Edit:
console.log("Data:", data) and console.log("loadmore_params:", loadmore_params); results below:
On further inspection, when trying to access the /wp-admin/admin-ajax.php url, I see a 0. When searching for this online, it has been suggested to use die(). However, when I've added die() to the end of knowledge-listing.php, it still shows me a 0.
Here is my localized script for reference:
global $wp_query;
wp_localize_script( 'theme', 'loadmore_params', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'posts' => json_encode( $wp_query->query_vars ),
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages,
'security' => wp_create_nonce("load_more")
) );
And actions:
add_action('wp_ajax_loadmore', 'pagination_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'pagination_ajax_handler'); // wp_ajax_nopriv_{action}
Just my 2 cents but "loadmore" as an action name is quite common and may be used by some other plugins/theme function. You should really consider switching to something namespaced like wp_ajax_mypluginname_loadmore.
That said, another common issue is that you perform the add_actions too late or maybe they never get hit by code before wp-admin-ajax does his thing.
Please be 100% you hit the add_actions BEFORE the code enter wp-admin-ajax.
To make a quick test you could move those line (included the function) in your child-theme functions.php file
Related
I tried make in the single post infinite scroll and load next post via ajax. I am using Jetpack for displaing share links of the post and also related posts. It works nice and initialize correctly when post was opened, but, when i send the content of the next post via Ajax, Jetpack doesn't initialize and consequently doesn't show the content... I tried to initialize using filters, but it doesn't work. The post's content generates and sends before the plugin's content initialize on the template. Is there any method to wait untill the plugin will be initialized, and send the full templated only after that? Or is there any other way to make it? I tried it on different plugins, not only Jetpack, the result the same. Sorry, if question may seems to very obvious, i am begginer.
Here is my code
JavaScript
const getNextPost = () => {
const bottomOffset = 1500,
loadBtn = $("#loading"),
main = $(".site-main"),
article = $("article"),
category = article.data("category");
let paged = 1;
$(window).scroll(function() {
if (
$(document).scrollTop() > $(document).height() - bottomOffset &&
!$("body").hasClass("loading") &&
category
) {
$.ajax({
type: "POST",
url: horisont.ajaxurl,
data: {
paged: paged,
category: category,
action: "loadnext",
},
beforeSend: function(xhr) {
console.log(category);
$("body").addClass("loading");
loadBtn.show();
},
success: function(data) {
let items = $(data);
paged++;
main.append(items);
loadBtn.hide();
$("body").removeClass("loading");
},
});
}
});
};
Php ajax
function loadnext_post() {
$category = ! empty( $_POST[ 'category' ] ) ? $_POST[ 'category' ] : '';
$paged = ! empty( $_POST[ 'paged' ] ) ? $_POST[ 'paged' ] : 1;
$paged ++;
$next_query = new WP_Query([
'p' => $next_id,
'post_type' => ['news', 'interview', 'post', 'post-analitiki'],
'posts_per_page' => 1,
'paged' => ($paged===1) ? 1 : $paged,
'category_name' => $category,
]);
while( $next_query->have_posts() ){
$next_query->the_post();
$jprp = Jetpack_RelatedPosts::init();
$callback = array( $jprp, 'filter_add_target_to_dom' );
add_filter( 'the_content', $callback, 40 );
get_template_part( 'template-parts/content', 'single-news' );
}
wp_reset_postdata( );
die;
}
add_action( 'wp_ajax_loadnext', 'loadnext_post' );
add_action( 'wp_ajax_nopriv_loadnext', 'loadnext_post' );
I am trying to get a list of all the posts in custom post type by taxonomy, I am stuck 3 days at this code, now i study with my father and he gave me a hint why my code is'nt working he a said i have too many args i will show you the code i hope anyone can help me understand why its not working and maybe if you really kind a explanation of the code in english
print_r(Array(
"1"=>"first",
"2"=>"second"
));
// just try to remove args that you don't need
//actually you need only one
$args = array(
'tax_query' => array(
'taxonomy' => 'your-custom-taxonomy',
'field' => 'slug',
'terms' => array( 'your-term' )
),
'post_type' => 'your-post-type'
);
$loop = new WP_Query($args);
if($loop->have_posts()) {
$term = $wp_query->queried_object;
while($loop->have_posts()) : $loop->the_post();
//Output what you want
echo '<li>'.get_the_title().'</li>';
endwhile;
}
So you have a custom post type called your-post-type
and you have a custom taxonomy called your-custom-taxonomy and you
want to get all the posts with a taxonomy term set called your-term.
You are doing it the right way with setting your arguments.
Notice: If you want to get all the posts of a custom post type, you do not need the whole 'tax_query' part of code.
I added some comments to describe what the code is doing:
$args = array( // define your arguments for query
'post_type' => 'your-post-type', // standard post type is 'post', you use a custom one
'tax_query' => array( // you check for taxonomy field values
array(
'taxonomy' => 'your-custom-taxonomy', // standard is 'category' you use a custom one
'field' => 'slug', // you want to get the terms by its slug (could also use id)
'terms' => 'your-term', // this is the taxonomy term slug the post has set
),
),
);
$loop = new WP_Query( $args ); // get post objects
// The Loop
if ( $loop ->have_posts() ) { // check if you received post objects
echo "<ul>"; // open unordered list
while ( $loop ->have_posts() ) { // loop through post objects
$loop ->the_post();
echo '<li>'.get_the_title().'</li>'; // list items
}
echo "</ul>"; // close unordered list
/* Restore original Post Data */
wp_reset_postdata(); // reset to avoid conflicts
} else {
// no posts found
}
Hope this helps!
EDIT: If you do not know how to use WP_Query
This code will get your wordpress posts ordered by their titles and output title and content. Put this inside a template file of your theme (learn something about template files: https://developer.wordpress.org/themes/basics/template-hierarchy/).
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => -1, // limit the number of posts if you like to
'orderby' => 'title',
'order' => 'ASC'
);
$custom_query = new WP_Query($args);
if ($custom_query->have_posts()) : while($custom_query->have_posts()) : $custom_query->the_post(); ?>
<h1><?php the_title(); ?></h1>
<?php the_content();?>
<?php endwhile; else : ?>
<p>No posts</p>
<?php endif; wp_reset_postdata(); ?>
You said you want to use a custom post type and do a taxonomy query. So you can adjust this with changing the arguments in $args.
I am having a problem getting a custom query to alphabetize. It keeps defaulting to displaying in the order of the date it was posted. Below is my php function.
function json_info2() {
// The $_REQUEST contains all the data sent via ajax
if ( isset($_REQUEST) ) {
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
// get values for all three drop-down menus
$status = $_REQUEST['status'];
$industry = $_REQUEST['services'];
$state = $_REQUEST['state'];
// array of values for each of the three drop-downs
$statusAll = array('complete','incomplete');
$industryAll = array('mining','textile','machinery');
$statesAll = array('SC','TX','WA');
// set $statusArray dependent on whether or not "all" is selected in the dropdown menu
if($status == "all") {
$statusArray = array( 'key' => 'status', 'value' => $statusAll, 'compare' => 'IN');
} else {
$statusArray = array( 'key' => 'status', 'value' => $status, 'compare' => '=');
}
if($industry == "all") {
$industryArray = array( 'key' => 'industry', 'value' => $industryAll, 'compare' => 'IN');
} else {
$industryArray = array( 'key' => 'industry', 'value' => $industry, 'compare' => '=');
}
if($state == "all") {
$stateArray = array( 'key' => 'state', 'value' => $statesAll, 'compare' => 'IN');
} else {
$stateArray = array( 'key' => 'state', 'value' => $state, 'compare' => '=');
}
$pages = array(
'post_type' => 'page',
'orderby' => 'title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => 5,
'meta_query' => array(
'relation' => 'AND',
$statusArray,
$industryArray,
$stateArray,
array(
'key' => '_wp_page_template',
'value' => 'template-individual-project.php',
'compare' => '='
)
)
);
// query results by page template
$my_query = new WP_Query($pages);
if($my_query->have_posts()) :
while($my_query->have_posts()) :
$my_query->the_post();
<li>
<?php the_title(); ?>
</li>
<?php
endwhile;endif;
wp_reset_query();
} // end of isset
?>
<?php
die();
}
add_action( 'wp_ajax_json_info2', 'json_info2' );
add_action( 'wp_ajax_nopriv_json_info2', 'json_info2' );
?>
This above function is called by the ajax function that follows:
function do_ajax() {
// Get values from all three dropdown menus
var state = $('#states').val();
var markets = $('#markets').val();
var services = $('#services').val();
$.ajax({
url: ajaxurl,
data: {
'action' : 'json_info2',
'state' : state,
'status' : markets,
'services' : services
},
success:function(moredata) {
// This outputs the result of the ajax request
$('#project-list').html( moredata );
$('#project-list').fadeIn();
}/*,
error: function(errorThrown){
var errorMsg = "No results match your criteria";
$('#project-list').html(errorMsg);
}*/
}); // end of ajax call
} // end of function do_ajax
Is there something simple that I'm missing here? I have a similar custom query on the page when it loads (although that initial load query doesn't have the select menu values as args), and they display in alphabetical order just fine. It's only after the ajax call to filter the list that they are no longer in order.
I have found the issue after googling the problem for quite a while. I read that some of the people who were having this problem found that their theme was using a plugin called Post Types Order. It overrides the ability to set the orderby arg.
I looked at the plugins, and sure enough, Post Types Order was there. Everything I read said that the problem could be solved by unchecking "auto sort" in the settings for the plugin. However, I did that, and orderby still didn't work. I had to completely deactivate the plugin to get orderby title to work.
since three hours I don't found the error in jquery.
I try to refresh a div, after I've created a file
Here is my View
<?php
echo CHtml::ajaxLink('Neuen Export erstellen',
Yii::app()->createUrl('exporter/create' ),
array(
'data' => array(),
'dataType' => 'json',
'type' => 'POST',
'complete' => "js:function(html){
$('#export-grid').fadeOut().fadeIn();
}",
'success' => "js:function(html){
$('#export-grid').replaceWith();
}"
),
array(
'class' => 'c2a_gray alignright',
'style' => 'font-size: 12px',
)
);
?>
** My Controller **
public function actionCreate()
{
// createfile();...
// do some stuff
$this->renderPartial('//users//exporter//_tmo', true, true);
}
complete Option works in ajaxLink function very well
but if I put alert(html) inside complete I got "Object object"
I don't know how to update export-grid with the new content.
please help me!
thx!
Yes if you try to alert html then it will return Object.
Please try alert(html.responseText).
As you probably know, Yii does not perform client-side validation with CHtml::ajaxSubmitButton. So after a long time spending on google and stackoverflow, I found that I should use the following link
a-simple-way-to-get-yii-client-side-form-validation-run-when-submitting-by-ajax
Now, It can perform client-side validation. But, the success or complete ajax functions does not fire after validation.
Any Idea?
To be more familiar with topic, I put my codes here:
Yii::app()->clientScript->registerCoreScript('yii');
Yii::app()->clientScript->registerScript('Yii Fix',";$.yii.fix = {
ajaxSubmit : {
beforeSend : function(form) {
return function(xhr,opt) {
form = $(form);
$._data(form[0], 'events').submit[0].handler();
var he = form.data('hasError');
form.removeData('hasError');
return he===false;
}
},
afterValidate : function(form, data, hasError) {
$(form).data('hasError', hasError);
return true;
}
}
};",CclientScript::POS_HEAD);
My form:
$uniqid = uniqid();
$form = $this->beginWidget('CActiveForm', array(
'id' => 'pagescontents-add-new-contents'.$uniqid,
'htmlOptions' => array(
'class' => 'form-horizontal',
'role' => 'form'
),
'enableClientValidation' => true,
'enableAjaxValidation'=>true,
'clientOptions' => array(
'validateOnSubmit' => true,
'validateOnChange'=>false,
'afterValidate'=>'js:$.yii.fix.ajaxSubmit.afterValidate',
),
));
//The rest of code
...
//Ajax submit button
$button_uniqid = uniqid();
echo CHtml::ajaxSubmitButton(Messages::getMessage('ADD_NEW'), $this->createUrl('pagescontents/addPage/'), array(
'beforeSend' => '$.yii.fix.ajaxSubmit.beforeSend("#pagescontents-add-new-contents'.$uniqid.'")',
'type'=>'POST',
'success' => "js:function(data){
$('#page_modal').html('');
$('.modal-backdrop').remove();
$('#pageContents_list').html(data);
}",
),
array(
'class' => 'btn btn-primary',
// 'data-dismiss' => 'modal',
'id' => 'deletesubmit_' . $button_uniqid
)
);
I try your code and find that if you remove the line "'enableAjaxValidation'=>true," your code will work perfectly please check it and let me know that is work for you too or not.