I'm using the ACF gallery field to let users create a gallery on front end and then I have an ajax call to save the gallery without page refresh.
If I remove the ajax save and use the default update post, all images in the gallery save correctly, but when I use my ajax save method only the last image in the gallery saves.
Here's my code:
Single post / form
<?php acf_form_head(); ?>
<?php get_header(); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php $args = array(
'form_attributes' => array(
'id'=>'modalAjaxTrying'
),
'submit_value' => __("update this badboy", 'acf'),
);
acf_form( $args );
?>
<?php endwhile; endif; ?>
<?php acf_enqueue_uploader();?>
<?php get_footer(); ?>
Ajax save in JS file
jQuery('form#modalAjaxTrying :submit').click(function(event){
event.preventDefault();
var form_data = {'action' : 'acf/validate_save_post'};
jQuery('form#modalAjaxTrying :input').each(function(){
form_data[jQuery(this).attr('name')] = jQuery(this).val()
})
form_data.action = 'save_my_data';
jQuery.post(ajaxurl, form_data)
.done(function(save_data){
alert('Added successFully :');
})
})
Functions.php
add_action( 'wp_ajax_save_my_data', 'acf_form_head' );
add_action( 'wp_ajax_nopriv_save_my_data', 'acf_form_head' );
Anyone looking to get ajax save to play nice with ACF gallery here ya go.
In your functions.php
add_action('acf/submit_form', 'my_acf_submit_form', 10, 2);
function my_acf_submit_form( $form, $post_id ) {
if(is_admin())
return;
//Test if it's a AJAX request.
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
echo $form['updated_message'];
die();
}
}
add_action( 'wp_ajax_save_my_data', 'acf_form_head' );
add_action( 'wp_ajax_nopriv_save_my_data', 'acf_form_head' );
function my_acf_save_post( $post_id ) {
// get new values
$value = get_field('add_images', $post_id);
In your JS file
acf.do_action('ready', $('body'));
$('form#modalAjaxTrying').on('submit', function(e){
e.preventDefault();
});
acf.add_action('submit', function($form){
$.ajax({
url: window.location.href,
method: 'post',
data: $form.serialize(),
success: function(data) {
acf.validation.toggle($form, 'unlock');
alert(data);
}
});
});
Related
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'm trying to make a custom category filter with ajax on frontpage.When I click on any of the custom taxonomy the content dissapears and I don't get any content.Custom post type are aranzman.
This is the page-usluge.php
<ul class="categories-filters">
<?php $args= array(
'show_option_all' => 'All posts', //Text for button All
'title_li' => __(''),
'taxonomy' => 'vrsta-aranzmana',
'post_type' => 'aranzman' );
wp_list_categories( $args ); ?> </ul>
<?php $query = new WP_query ( $args );
if ( $query->have_posts() ) { ?>
<div id="main-content" class="row">
<div id="inside">
<div class="container">
<?php while ( $query->have_posts() ) : $query->the_post(); ?>
<article>
<a class="xiong-articlebox" href="<?php the_permalink();?>">
<header>
<h3><?php the_title( );?></h3> <p><em><?php the_date( 'j.n.Y'); ?> </em></p> </header>
<p><?php the_excerpt();?></p> </a> </article>
<?php endwhile; }?>
</div><!-- container-->
</div><!--inside -->
</div> <!--row -->
This is the ajax.js
jQuery(function(){
var mainContent = jQuery('#main-content'),
cat_links = jQuery('ul.categories-filters li a');
cat_links.on('click', function(e){
e.preventDefault();
el = jQuery(this);
var value = el.attr("href");
mainContent.animate({opacity:"0.5"});
mainContent.load(value + " #inside", function(){
mainContent.animate({opacity:"1"});
});
});
});
And this is the functions.php calling the ajax.js
function ajax_theme_scripts() {
//Ajax filter scripts
wp_register_script( 'ajax', get_stylesheet_directory_uri() . '/js/ajax.js', array( 'jquery' ), '1.0.0', true );
wp_enqueue_script( 'ajax' );
}
add_action( 'wp_enqueue_scripts', 'ajax_theme_scripts' );
The 'not' working demo or example is on this link
DEMO
First of all, Wordpress already comes with an ajax handler (admin-ajax.php).
Here is the link to documentation for that: https://codex.wordpress.org/AJAX_in_Plugins.
Briefly, what you have to do is:
1) add_action('wp_ajax_nopriv_{your_action_id}', callback)
Your call back here is supposed to be the filter function
2) Write a javascrip ajax:
$.ajax({
method: "expected method(POST)",
url: "wp-admin/admin-ajax.php (should be called dynamically with wp_localize_script => https://codex.wordpress.org/Function_Reference/wp_localize_script)"
dataType: "expected dataType(JSON)",
data: {
action: {your_action_id},
"other data that you want to send"
}
success: function(response){}
});
To be able to handle the content of the response, you need to send as part of your response the html/text of the result. In this way, all you need to do is to use the simple jquery method $(selector).html(htmlOfResult);
To send data to your javascript success callback, you can use wp_send_json() https://codex.wordpress.org/Function_Reference/wp_send_json.
Here is for ajax.js
jQuery(document).ready(function($) {
$('ul.categories-filters li a').on('click', function(event) {
event.stopPropagation();
event.preventDefault();
$.ajax({
method: "POST",
url: Object_var.ajax_url_attr,
dataType: "JSON",
data: {
action: "myfilter_action",
// I think you are using the href to check filter
filter_req: $(this).attr('href')
},
success: function(response) {
if(typeof response != "undefined")
$('#inside .container').html(response.html_text);
}
});
});
});
here is for the function.php
<?php
add_action('wp_enqueue_scripts', function(){
// Register first the ajax.js script
wp_enqueue_script('handle_of_script', 'link/to/ajax.js');
// Now send variable to the script
wp_localize_script('handle_of_script', "Object_var", [
"ajax_url_attr" => admin_url( 'admin-ajax.php' )
]);
});
add_action("wp_ajax_nopriv_myfilter_action", function(){
$filter_req = $_POST['filter_req'];
// Run filter of whatever
$query_result = your_filter();
// Convert values to html/text
$html_text = convert_to_html_text($query_result);
// Send data to jQuery AJAX
wp_send_json(
"html_text" => $html_text
);
wp_exit();
});
function convert_to_html_text($query) {
$html = "";
ob_start();
// Maybe check if query is valid or have post ...
?>
<?php while ( $query->have_posts() ): $query->the_post(); ?>
<article>
<a class="xiong-articlebox" href="<?php the_permalink(); ?>">
<header>
<h3><?php the_title(); ?></h3>
<p>
<em><?php the_date( 'j.n.Y'); ?></em>
</p>
</header>
<p><?php the_excerpt();?></p>
</a>
</article>
<?php endwhile;?>
<?
$html_text = ob_get_contents();
return $html;
}
I think this could help!
I am trying to build a simple interface in Woocommerce where a product gets added straight to the mini cart next to it with AJAX, rather than having the page refresh every time you add an item to the cart. Unfortunately I cannot get the AJAX to work and the page just keeps refreshing.
woocommerce.php - the default woocommerce page:
<?php
//LOOP THROUGH ALL PRODUCTS
$args = array( 'post_type' => 'product');
$loop = new WP_Query( $args );
echo "<ul class='mylisting'>";
while ( $loop->have_posts() ) : $loop->the_post();
global $product;
$id = $product->get_id();
$item_name = $product->get_name();
if( $product->is_type( 'variable' ) ){
$class = "variable-product";
} else {
$class = NULL;
}
//OUTPUT PRODUCTS
?>
<li>
<a class="menu-link <?php echo $class; ?>" data-product_id="<?php echo $id; ?>" href="/wpdev/shop/?add-to-cart=<?php echo $id; ?>"><?php echo $item_name." - ".$id; ?></a>
</li>
<?php if( $product->is_type( 'variable' ) ) : ?>
<div id="product-popup-<?php echo $id; ?>" class="product-popup">
<div class="popup-inner">
<?php woocommerce_variable_add_to_cart(); ?>
</div>
</div>
<?php endif; ?>
<?php
endwhile;
echo "</ul>";
wp_reset_query();
?>
<!-- DISPLAY MINI CART -->
<div id="mini-cart-container">
<?php woocommerce_mini_cart(); ?>
</div>
main.js - Main javascript file:
$('.menu-link').click(function(){
jQuery.ajax({
url : woocommerce_params.ajax_url,
type : 'post',
data : {
'action': 'ajax_update_mini_cart'
},
success : function( response ) {
$('#mini-cart-container').html(response);
}
});
});
functions.php
function ajax_update_mini_cart() {
echo wc_get_template( 'cart/mini-cart.php' );
die();
}
add_filter( 'wp_ajax_nopriv_ajax_update_mini_cart', 'ajax_update_mini_cart' );
add_filter( 'wp_ajax_ajax_update_mini_cart', 'ajax_update_mini_cart' );
The goal is to get the woocommerce_mini_cart() function to update with ajax. Is this possible?
I suspect the problem lies with the way I have coded the javascript ajax function, but I'm not sure. Any help would be greatly appreciated.
UPDATE: Moe's solution below has now been added, which has stopped the page reloading but the cart still doesn't update. Echoing some text inside the ajax_update_mini_cart() function does ajax that text inside the mini-cart-container div where the mini-cart should be, which proves (I think) that the javascript function and the php function is working. I think for some reason the problem comes when the echo wc_get_template( 'cart/mini-cart.php' ); is placed inside the function. Does anyone know why this is?
its following the href. try the following
$('.menu-link').click(function(e){
e.preventDefault();
jQuery.ajax({
url : woocommerce_params.ajax_url,
type : 'post',
data : {
'action': 'ajax_update_mini_cart'
},
success : function( response ) {
$('#mini-cart-container').html(response);
}
});
});
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 send AJAX data to my wordpress table but all I can get from my PHP is a 0. Its on the admin side. Can anyone help me?
Also all of this code is inside my plugin-admin.php file inside my plugin folder.
<?php
if ( ! defined( 'ABSPATH' ) || ! current_user_can( 'manage_options' ) ) exit;
global $wpdb;
global $wp_version;
$results = $wpdb -> get_results(
"
SELECT ID, post_title, post_excerpt
FROM $wpdb->posts
WHERE post_type = 'post' and post_status NOT LIKE 'auto-draft'
AND post_title NOT LIKE 'Auto Draft'
AND post_status = 'publish'
ORDER BY post_title
"
);
add_action( 'wp_ajax_featured_submit_action', 'featured_submit_callback' );
function featured_submit_callback(){
echo "hi";
wp_die();
}
?>
<div class="wrap">
<h2>Select Posts</h2>
<select id="selected-posts" multiple="multiple">
<?php
foreach ( $results as $result ){
?><option value="<?php echo $result->ID; ?>"> <?php echo $result->post_title; ?> </option> <?php
}
?>
</select>
<br>
<input type="submit" id="sposts-submit"></input>
</div>
<script>
jQuery(document).ready(function($) {
var spostsarray = new Array();
//Click button
$("#sposts-submit").click(function(){
var spostsarray = new Array();
$("#selected-posts").each(function(item){
spostsarray.push( $(this).val() );
});
console.log(spostsarray);
var data = {
"action": "featured_submit_action",
"posts": spostsarray
}
$.ajax({
url: "<?php echo admin_url('admin-ajax.php'); ?>",
type: "POST",
action: "featured_submit_action",
data: {"posts": spostsarray},
success: function(data){
console.log(data);
}
});
});
});
</script>
I've condensed it a bit but the general idea is that I can grab all the recent posts and the user can select which ones they want to feature, send that to the PHP method and edit the table with it.
The problem is with my AJAX callback I only ever return 0 and not the data sent from the javascript.
SOLVED:
After some help from Rohil_PHPBeginner I figured it out. The reason it didn't work is that I was executing the code from the menu page at at that point it was too late to add a hook. Here is the page I used to solve it:
AJAX in WP Plugin returns 0 always
Below code worked perfectly fine for me:
<?php
global $wpdb;
global $wp_version;
$results = $wpdb -> get_results(
"
SELECT ID, post_title, post_excerpt
FROM $wpdb->posts
WHERE post_type = 'post' and post_status NOT LIKE 'auto-draft'
AND post_title NOT LIKE 'Auto Draft'
AND post_status = 'publish'
ORDER BY post_title
"
);
?>
<div class="wrap">
<h2>Select Posts</h2>
<select id="selected-posts" multiple="multiple">
<?php
foreach ( $results as $result ){
?><option value="<?php echo $result->ID; ?>"> <?php echo $result->post_title; ?> </option> <?php
}
?>
</select>
<br>
<input type="submit" id="sposts-submit"></input>
</div>
<?php
add_action( 'wp_ajax_featured_submit_action', 'featured_submit_callback' );
add_action( 'wp_ajax_nopriv_featured_submit_action', 'featured_submit_callback' );
function featured_submit_callback(){
echo "hi";
wp_die();
}
?>
<script>
jQuery(document).ready(function($) {
//Click button
$("#sposts-submit").click(function(){
var spostsarray = new Array();
$("#selected-posts").each(function(item){
spostsarray.push( $(this).val() );
});
console.log(spostsarray);
var data = {
"action": "featured_submit_action",
"posts": spostsarray
}
$.ajax({
url: ajaxurl,
type: "POST",
data: data,
success: function(data){
console.log(data);
}
});
});
});
</script>
You don't need to pass the AJAX url in that way because when I used your code, it is showing me with PHP. WordPress provides a default url for AJAX so you can use that( ajaxurl which I used in below code).
Other than that You have not added code for no-privilege user (if it is going to use only for privileged user then it is okay otherwise you need to add code for that).
WordPress returns 0 when an ajax call doesn't find a valid callback function (though the 0 could be return from many other things).
WordPress looks for callbacks matching wp_ajax_{callback} when a user is logged in and wp_ajax_nopriv_{callback} when the user is logged out. {callback} is populated with the POST'd value of the "action" hidden input. Note that you're not passing the action into your AJAX call. You should change:
data: {"posts": spostsarray},
to
data: data
Since you're not going to match a callback function without passing in action, WordPress is returning 0