I'm building a site within WordPress which will display two rows of images at the start, then on button click, two more, dynamically.
I have four files involved in this process:
case-study-card.php: Which holds the markup for the each card.
home.php: Where the load more button is created.
load-more.js
ajax-loaders.php
However, I'm stumped on where my AJAX is falling apart? I feel as if
/*************/
// load-more.js
/*************/
jQuery(function($){
$('#loadmore').click(function(){
var column_width = $(this).data('column-width');
var max_num_pages = $(this).data('max-num-pages');
var ignore = $(this).data('featured');
var post_type = $(this).data('type');
var button = $(this),
data = {
action:'loadmore',
query: loadmore_params.posts,
page : loadmore_params.current_page,
security : loadmore_params.security
};
$.ajax({
url : loadmore_params.ajaxurl,
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...');
console.log ("before sending ajax"); // works
},
success : function( data ){
if( data ) {
console.log("test")
button.text( 'Load More' ).prev().before(data); // insert new posts
loadmore_params.current_page++;
// where to insert new posts...
console.log("now inserting new posts");
$('.case-studies-container').find('.case-card').last().after( data );
console.log("found card");
// if it's the last page in the query, remove the button
if ( loadmore_params.current_page == max_num_pages )
button.remove();
console.log (data);
} else {
// if no data, remove the button as well
button.remove();
}
},
error : function(error){
console.log(error);
}
});
});
});
<!-- In case-study-card.php -->
<div class="case-card" >
<div class="case-card__wrapper">
<h4 class="case-card__title">
Title
</h4>
</div>
</div>
<!-- in home.php
* After looping through and displaying the initial 5 cards, display the button at the bottom
-->
<?php
if ($the_query->found_posts > 5 ){
echo "<div class='case-study__loadmore'><a id='loadmore'>Load more</a>";
}
?>
<!-- ajax-loaders.php -->
<?php
function ajax_handler(){
check_ajax_referer('load_more', 'security');
//prepare arguments for query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
$args['post__not_in'] = explode(',',$_POST['exclude']);
$args['max_num_pages'] = $_POST['max_num_pages'];
$cols = $_POST['columns'];
$type = $_POST['post_type'];
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
endwhile;
endif;
die;
}
add_action('wp_ajax_loadmore', 'ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'ajax_handler'); // wp_ajax_nopriv_{action}
?>
I believe everything after success : function( data ) in load-more.js is not working and I'm not sure why? I also get a admin-ajax.php 400 (Bad Request) error, a file that I have not seen or worked on in this project ...
Edit:
asset-loader.php
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")
) );
wp_localize_script( 'theme', 'repeater_loadmore_params', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages,
'security' => wp_create_nonce("repeater_field_nonce")
) );
Edit 2:
I believe the ajax handler url : loadmore_params.ajaxurl is working.
When I have url : loadmore_params.ajaxurl the button text changes from "Load more" to "Loading".
When I have url : ajaxurl the button doesn't change beforeSend.
Which makes me think the handler is working fine, but anything within success : function( data ){ isn't working and I'm not sure why.
Place your localize script also so it may be debug properly.
Related
Have been trying to solve this for a couple days and decided to just break down and ask for some insight. I'm basing what I have off of these two solutions:
Change items tax rate in WooCommerce checkout based on radio buttons
Add a dynamic fee based on a select field in WooCommerce Checkout
I'm trying to use a drop down/select to change the tax class on the checkout page of WooCommerce.
I've left a lot alone from the two above examples but am still not getting the results expected. I also need to store & place the delivery location in the admin area & emails but need to get this tax class change issue sorted first.
Below is what I have right now. It seems like it should be working but alas, no joy.
// Add a custom select fields for packing option fee
add_action( 'woocommerce_after_order_notes', 'checkout_shipping_form_packing_addition', 20 );
function checkout_shipping_form_packing_addition( ) {
$domain = 'woocommerce';
echo '<tr class="packing-select"><th>' . __('Pickup Location', $domain) . '</th><td>';
$chosen = WC()->session->get('chosen_packing');
// Add a custom checkbox field
woocommerce_form_field( 'chosen_packing', array(
'type' => 'select',
'class' => array( 'form-row-wide packing' ),
'options' => array(
'' => __("Please select a location...", $domain),
'BELGIUM - LOC' => sprintf( __("BELGIUM - LOC", $domain) ),
'BROOTEN - LOC' => sprintf( __("BROOTEN - LOC", $domain) ),
'OWATONNA - LOC' => sprintf( __("OWATONNA - LOC", $domain) ),
),
'required' => true,
), $chosen );
echo '</td></tr>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_shipping_packing_script' );
function checkout_shipping_packing_script() {
// Only checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) :
WC()->session->__unset('chosen_packing');
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'select#chosen_packing', function(){
var p = $(this).val();
console.log(p);
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'packing': p,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log('response: '+result); // just for testing | TO BE REMOVED
},
error: function(error){
console.log(error); // just for testing | TO BE REMOVED
}
});
});
});
</script>
<?php
endif;
}
// Php Ajax (Receiving request and saving to WC session)
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );
function woo_get_ajax_data() {
if ( isset($_POST['packing']) ){
$packing = sanitize_key( $_POST['packing'] );
WC()->session->set('chosen_packing', $packing );
echo json_encode( $packing );
}
die(); // Alway at the end (to avoid server error 500)
}
// Add a custom dynamic packaging fee
add_action( 'woocommerce_before_calculate_totals', 'change_tax_class_conditionally', 1000 );
function change_tax_class_conditionally( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$domain = "woocommerce";
$packing_fee = WC()->session->get( 'chosen_packing' ); // Dynamic packing fee
if ( $packing_fee === 'BELGIUM - LOC' ) {
//$label = __("Bag packing fee", $domain);
$tax_class = '5 Percent';
}
if ( $packing_fee === 'BROOTEN - LOC' ) {
//$label = __("Bag packing fee", $domain);
$tax_class = '0 Percent';
}
if ( $packing_fee === 'CHER-MAKE - LOC' ) {
//$label = __("Bag packing fee", $domain);
$tax_class = 'Reduced Rates';
}
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
if( $choice === $field_value ) {
$cart_item['data']->set_tax_class($tax_class);
}
}
}
// Field validation, as this packing field is required
add_action('woocommerce_checkout_process', 'packing_field_checkout_process');
function packing_field_checkout_process() {
// Check if set, if its not set add an error.
if ( isset($_POST['chosen_packing']) && empty($_POST['chosen_packing']) )
wc_add_notice( __( "Please choose a packing option...", "woocommerce" ), 'error' );
}
There is a button on the site, when you click on that button, new posts are loaded.Everything works fine on the desktop, but it breaks down on the phone.
XHR failed loading: POST "https://test-5.vbbn.in/wp-admin/admin-ajax.php".
send # jquery.js?ver=1.12.4-wp:4
ajax # jquery.js?ver=1.12.4-wp:4
n. # jquery.js?ver=1.12.4-wp:4
(anonymous) # (index):1732
dispatch # jquery.js?ver=1.12.4-wp:3
r.handle # jquery.js?ver=1.12.4-wp:3
add_action( 'wp_footer', 'my_action_javascript' );
function my_action_javascript() { ?>
<script>
jQuery(document).ready(function($) {
var page = 2;
var post_count = jQuery('#posts').data('count');
var ajaxurl = "<?php echo admin_url('admin-ajax.php');?>"
jQuery('#load_more').click(function () {
var data = {
'action': 'my_action',
'page': page
};
jQuery.post(ajaxurl, data, function(response) {
jQuery('#posts').append(response);
if (post_count == page){
jQuery('#load_more').hide();
}
page++;
});
});
});
</script> <?php
}
add_action( 'wp_ajax_my_action', 'my_action' );
function my_action() {
$args = array(
'post_type' => 'post',
'category_name'=> 'nouvelles',
'paged' => $_POST['page'],
);
$the_query = new WP_Query( $args ); ?>
<?php if ( $the_query->have_posts() ) : ?>
<?php
while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
Tried to add e.preventDefault, to avoid rebooting that does not write the POST then pass event to the function, but it shows that e.preventDefault is not a function.
Website - https://test-5.vbbn.in/
Hope for any help. thanks
You are trying to hit an url using admin ajax. but url is not returning 200 as response. It is returning 400(not found) . I just tested the url by clicking button. Please see the screenshot below that I attached.
Now fix the issue and be confirm that your action is available for admin-ajax
I"m using the tutorial from this blog post to implement Ajax Load More functionality. https://rudrastyh.com/wordpress/load-more-posts-ajax.html
I've successfully implemented this on my archive page for all blog posts. However, I've got several "RElated Posts" sections that use custom WP Queries that I can't get to work. I've tried the solution in this comment: https://rudrastyh.com/wordpress/load-more-posts-ajax.html#comment-1055
It loads new posts, but they are not adhering to the argumenets of the custom query (specifically displaying posts only in the same category).
The custom query is working (it displays 4 related posts from the same category). When i'm loading more, it is not respecting pagination (it's loading 6 posts instead of 4) and it is not respecting the query (it is loading posts not in the same category).
<div class="related-blog-posts gray-bg pt-5 pb-5 blog">
<div class="related-title pb-3">
<h1 class="mb-2">Related Stories</h1>
<img src="/dcustom/wp-content/uploads/2019/04/Path-137#2x.png" />
</div><!-- scroll-down-->
<div class="container">
<div class="row">
<?php
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$query_args = array(
'category__in' => wp_get_post_categories( $post->ID ),
'paged' => $paged,
'post_type' => 'post',
'posts_per_page' => 4,
'post__not_in' => array( $post->ID ),
'orderby' => 'date',
'order' => 'DESC'
);
$third_query = new WP_Query( $query_args ); ?>
<?php
//Loop through posts and display...
if($third_query->have_posts()) : ?>
<?php while ($third_query->have_posts() ) : $third_query->the_post(); ?>
<?php get_template_part('template-parts/content-related-blog-posts'); ?>
<?php endwhile; ?><!-- end the loop-->
<?php endif; ?>
<?php wp_reset_postdata(); ?>
<?php // don't display the button if there are not enough posts
if ( $third_query->max_num_pages > 1 )
echo '<a class="custom_loadmore btn btn-primary">More posts</a>'; // you can use <a> as well
?>
<?php endif; ?><!-- end loop if--->
</div><!-- row -->
</div><!-- container -->
</div><!-- related-case-studies-->
<script>
var test = '<?php echo serialize( $third_query->query_vars ) ?>',
current_page_myajax = 1,
max_page_myajax = <?php echo $third_query->max_num_pages ?>
</script>
<script src="<?php bloginfo('template_url')?>/js/myloadmore.js"></script>
jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error
$('.misha_loadmore').click(function(){
var button = $(this),
data = {
'action': 'loadmore',
'query': misha_loadmore_params.posts, // that's how we get params from wp_localize_script() function
'page' : misha_loadmore_params.current_page
};
$.ajax({ // you can also use $.post here
url : misha_loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().after(data); // insert new posts
misha_loadmore_params.current_page++;
if ( misha_loadmore_params.current_page == misha_loadmore_params.max_page )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
}
});
});
$('.custom_loadmore').click(function(){
//custom query on front-page.php
var button = $(this),
data = {
'action': 'loadmore',
'query': test,
'page' : current_page_myajax
};
$.ajax({
url : '/dcustom/wp-admin/admin-ajax.php', // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'More posts' ).prev().after(data); // insert new posts
current_page_myajax++;
if ( current_page_myajax == max_page_myajax )
button.remove(); // if last page, remove the button
} else {
//button.remove(); // if no data, remove the button as well
}
}
});
});
});
function misha_my_load_more_scripts() {
global $wp_query;
// In most cases it is already included on the page and this line can be removed
wp_enqueue_script('jquery');
// register our main script but do not enqueue it yet
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/js/myloadmore.js', array('jquery') );
// now the most interesting part
// we have to pass parameters to myloadmore.js script but we can get the parameters values only in PHP
// you can define variables directly in your HTML but I decided that the most proper way is wp_localize_script()
wp_localize_script( 'my_loadmore', 'misha_loadmore_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // WordPress AJAX
'posts' => json_encode( $wp_query->query_vars ), // everything about your loop is here
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $wp_query->max_num_pages,
) );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'misha_my_load_more_scripts' );
/* AJAX LOOP FOR THE ARCHIVE PAGE */
function misha_loadmore_ajax_handler(){
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
// it is always better to use WP_Query but not here
query_posts( $args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post();
// look into your theme code how the posts are inserted, but you can use your own HTML of course
// do you remember? - my example is adapted for Twenty Seventeen theme
get_template_part( 'template-parts/content-index', get_post_format() );
// for the test purposes comment the line above and uncomment the below one
// the_title();
endwhile;
endif;
die; // here we exit the script and even no wp_reset_query() required!
}
add_action('wp_ajax_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'misha_loadmore_ajax_handler'); // wp_ajax_nopriv_{action}
I have a custom taxonomy in WordPress called Case studies.
Home.php is a page. Within home.php I have ran a loop to get all the case studies:
<?php
// only display 5 posts at first, then load 5 more on button click
$args = array('post_type' => 'case-studies', 'posts_per_page' => 5 );
$the_query = new WP_Query($args);
if ( $the_query->have_posts() ) {
echo "<div id='customers' class='case-studies-container'>"; // If there are results, create a single div in which all case studies will sit.
// run a loop to get data from all the posts that exist
while ($the_query->have_posts() ) {
$the_query->the_post();
tp_get_part( 'templates/snippets/case-study-card',
array(
'heading' => get_the_title(),
'subheading' => get_field( 'case_study_subheading'),
)
);
}
echo "<div><input type='button' id='loadmore' value='Load more'/></div>
</div>" // case-studies-container closed;
wp_reset_postdata();
} else {
// no posts found
}
?>
On #loadmore button click, I want it to load 5 more posts from the DB and display them. To accomodate this, I have the following JS within *home.php*
<script type="text/javascript">
$(document).ready(function(){
$('#loadmore').click(function(){
// alert('Hello world');
// load more case studies here
jQuery(function($){
var column_width = $(this).data('column-width');
var max_num_pages = $(this).data('max-num-pages');
var ignore = $(this).data('featured');
var post_type = $(this).data('type');
var button = $(this),
data = {
action:'loadmore',
query: loadmore_params.posts, // that's how we get params from wp_localize_script() function
page : loadmore_params.current_page,
security : loadmore_params.security,
columns : column_width,
exclude : ignore,
max_num_pages : max_num_pages,
post_type : post_type
};
$.ajax({
url : loadmore_params.ajaxurl, // AJAX handler
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
button.text('Loading...'); // change the button text, you can also add a preloader image
},
success : function( data ){
if( data ) {
button.text( 'Load More' ).prev().before(data); // insert new posts
loadmore_params.current_page++;
$('.case-studies-container').find('.case-card').last().after( data ); // where to insert posts
if ( loadmore_params.current_page == max_num_pages )
button.remove(); // if last page, remove the button
// you can also fire the "post-load" event here if you use a plugin that requires it
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // if no data, remove the button as well
}
},
error : function(error){ console.log(error) }
});
});
});
});
</script>
And the following AJAX written in ajax-loaders.php:
<?php
function ajax_handler(){
check_ajax_referer('load_more', 'security');
// prepare our arguments for the query
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // we need next page to be loaded
$args['post_status'] = 'publish';
$args['post__not_in'] = explode(',',$_POST['exclude']);
$args['max_num_pages'] = $_POST['max_num_pages'];
$cols = $_POST['columns'];
$type = $_POST['post_type'];
query_posts($args );
if( have_posts() ) :
// run the loop
while( have_posts() ): the_post(); ?>
<div class="<?php echo ($cols ? 'col-'.$cols : 'col-3') .' '. ($type === 'case-study' ? 'case-studies' : 'article__item'); ?> grid__item" id="<?php echo get_the_id(); ?>">
<?php
tp_get_part( 'templates/snippets/case-study-card',
array(
'filterable' => true,
'post' => $post,
'type' => get_cpt_term(get_the_id(), 'case-studies')
)
);
?>
</div>
<?php
endwhile;
endif;
die;
}
add_action('wp_ajax_loadmore', 'ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore', 'ajax_handler'); // wp_ajax_nopriv_{action}
?>
With all these files set up, on button click, nothing happens? If I uncomment out the alert, the alert occurs which means the trigger is occurring, but unsure on where my load more functionality is going wrong?
I'm trying to use an AJAX form on my Wordpress site to update a custom user meta (company_name) I created with ACF but it is not updating. If I use a built-in user meta such as first_name or last_name, it's working. But for whatever reason, custom user fields are not updating.
Thanks in advance
HTML form
<form id="um_form2" method="POST">
<p>
<label for="um_key">
Enter your last name:
<input type="text" name="um_key" id="um_key" value="" style="width:100%;" />
</label>
<input type="submit" value="Submit"/>
</p>
</form>
Snippet Script 1
function theme_enqueue2() {
$theme_url = get_template_directory_uri(); // Used to keep our Template Directory URL
$ajax_url = admin_url( 'admin-ajax.php' ); // Localized AJAX URL
// Register Our Script for Localization
wp_register_script(
'um-modifications2', // Our Custom Handle
"{$theme_url}/scripts/um-modifications2.js", // Script URL, this script is located for me in `theme-name/scripts/um-modifications.js`
array( 'jquery' ), // Dependant Array
'1.0', // Script Version ( Arbitrary )
true // Enqueue in Footer
);
// Localize Our Script so we can use `ajax_url`
wp_localize_script(
'um-modifications2',
'ajax_url',
$ajax_url
);
// Finally enqueue our script
wp_enqueue_script( 'um-modifications2' );
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue2' );
Snippet 2
function um_modifications_callback2() {
// Ensure we have the data we need to continue
if( ! isset( $_POST ) || empty( $_POST ) || ! is_user_logged_in() ) {
// If we don't - return custom error message and exit
header( 'HTTP/1.1 400 Empty POST Values' );
echo 'Could Not Verify POST Values.';
exit;
}
$user_id = get_current_user_id(); // Get our current user ID
$um_val = sanitize_text_field( $_POST['company_name'] ); // Sanitize our user meta value
update_user_meta( $user_id, company_name, $um_val ); // Update our user meta
wp_update_user( array(
'ID' => $user_id,
// 'user_email' => $um_user_email,
)
);
echo "<script>window.close();</script>";
exit;
}
add_action( 'wp_ajax_nopriv_um_cb2', 'um_modifications_callback2' );
add_action( 'wp_ajax_um_cb2', 'um_modifications_callback2' );
Backend JavaScript
// Declare our JQuery Alias
jQuery( 'document' ).ready( function( $ ) {
// Form submission listener
$( '#um_form2' ).submit( function() {
// Grab our post meta value
var um_val2 = $( '#um_form2 #um_key' ).val();
// Do very simple value validation
if( $( '#um_form2 #um_key' ).val().length ) {
$.ajax( {
url : ajax_url, // Use our localized variable that holds the AJAX URL
type: 'POST', // Declare our ajax submission method ( GET or POST )
data: { // This is our data object
action : 'um_cb2', // AJAX POST Action
'company_name': um_val, // Replace `um_key` with your user_meta key name
}
} )
.success( function( results ) {
alert("success!");
window.location.href=window.location.href;
} )
.fail( function( data ) {
console.log( data.responseText );
console.log( 'Request failed: ' + data.statusText );
} );
} else {
// Show user error message.
}
return false; // Stop our form from submitting
} );
} );
Found the correct way...
update_field('company_name', $_POST['company_name'], 'user_'.$user_id.'');
instead of update_user_meta