I'm trying to do an AJAX request in an WordPress plugin. The request is initiated on the front page embedded in an article using a custom shortcode.
I tried to combine infos from the documentation and this tutorial.
However something is going wrong when testing that method... the AJAX query hook isn't called.
This is how my page.php script is called for short code delivery:
add_shortcode('testshortcode', 'TestShortCodeFunction');
function TestShortCodeFunction($attributes)
{
ob_start();
include(__DIR__.'/page.php');
return ob_get_clean();
}
This is my compacted test script page.php:
<?php
add_action('wp_ajax_test', 'Test');
add_action('wp_ajax_nopriv_test', 'Test');
// do_action('wp_ajax_nopriv_test'); this calls Test()
function Test()
{
echo 'Hallo';
die();
}
?>
<script type='text/javascript'>
jQuery(document).ready(function() {
console.log("JS query started");
// The following does not call test()
jQuery.ajax({
type: "POST",
url: "http://127.0.0.1/wordpress/wp-admin/admin-ajax.php?action=test",
success: function(data) {
console.log("Query returned: "+data);
}
});
});
</script>
Output on the console is:
JS query started
Query returned: 0
The Test() function is never call according to the PHP debugger.
The admin-ajax.php is executed according to the network monitor (URL http://127.0.0.1/wordpress/wp-admin/admin-ajax.php?action=test) but returns 0.
Inside admin-ajax.php do_action('wp_ajax_test') is called according to the PHP debugger.
I'd be really surprised if you managed to make those Ajax action hooks work inside an Output Buffer.
AFAIK, we should only use PHP ob_* functions as last resort.
Here's a standard implementation. A JavaScript file will be enqueued inside the shortcode callback function, and inside it we fire a document.ready Ajax call. The admin-ajax.php URL is passed to a JS object using wp_localize_script. Check the code comments for more info and the Codex for details on each WP function:
<?php
/**
* Plugin Name: (SO) Simple Ajax Shortcode
* Description: Fire an Ajax action when rendering a shortcode
* Author: brasofilo
* Plugin URL: https://stackoverflow.com/a/22585520/1287812
*/
add_shortcode( 'testshortcode', 'shortcode_so_22579460' );
add_action( 'wp_enqueue_scripts', 'enqueue_so_22579460' );
add_action( 'wp_ajax_Test_SO', 'Test_SO' );
add_action( 'wp_ajax_nopriv_Test_SO', 'Test_SO' );
/**
* Enqueue our script inside the shortcode
*/
function shortcode_so_22579460($attributes)
{
wp_enqueue_script( 'my-script' );
return '<h1>Check the broswer console.</h1>';
}
/**
* Register and localize our script
*/
function enqueue_so_22579460()
{
wp_register_script(
'my-script',
plugin_dir_url( __FILE__ ) . 'ajax.js',
array( 'jquery' ) // enqueue jQuery as dependency
);
// We can pass any number of PHP data to the JS 'wp_ajax' object
// Here, only the basics, Ajax URL and a security check
wp_localize_script(
'my-script',
'wp_ajax',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'ajax_post_validation' )
)
);
}
/**
* Ajax callback
*/
function Test_SO()
{
// Security check
check_ajax_referer( 'ajax_post_validation', 'security' );
// Demonstrative boolean value to return
$random = ( rand() % 2 != 0 );
if( $random )
wp_send_json_error( array( 'error' => 'Random is ODD' ) );
else
wp_send_json_success( 'Random is EVEN' );
}
And the JavaScript file (ajax.js) stored in the same folder as the plugin file:
jQuery(document).ready( function($)
{
var data = {
action: 'Test_SO',
security: wp_ajax.ajaxnonce
};
$.post(
wp_ajax.ajaxurl,
data,
function( response )
{
// Errors
if( !response.success )
{
// No data came back, maybe a security error
if( !response.data )
console.log( 'AJAX ERROR: no response' );
// Error from PHP
else
console.log( 'Response Error: ' + response.data.error );
}
// Success
else
console.log( 'Response Success: ' + response.data );
}
);
});
Here's a similar answer of mine using OOP and jQuery commands to trigger the action. And an article of interest.
Related
I am running into some issues with the AJAX portion of a Wordpress site feature that takes a zip code entered on a form uses a PHP function to find if the zip code refers to a specific location and returns a permalink to that location.
My first question was about the form I built. Right now I have the form-action blank because I don't want the form to really go anywhere, just make the AJAX call. Is there anything extra I need to do in the form to indicate the data entered should go to an AJAX function?
<form id="zipcode" action="" method="post"><input class="form-control search-input" autocomplete="off" name="zipcode" type="text" value="" placeholder="Enter Zip Code" />
The next question I have is about the filter function in my functions.php file. I'm not sure exactly how to go about getting the form data passed inot the filter data, this is what I have tried below, I also included the zip_search function which returns the permalink.
/**
* LOCATION SEARCH FILTER AJAX
*
* call location search filter ajax
*
* #return ajax json data via function.
*/
add_action( 'wp_ajax_locations_search', 'prefix_ajax_locations_search' );
add_action( 'wp_ajax_nopriv_locations_search', 'prefix_ajax_locations_search' ); //used for handling AJAX requests from unauthenticated users
function prefix_ajax_zip_search_filter() {
// Handle request then generate response using WP_Ajax_Response
$zipcode = $_POST[ 'zipcode' ];
//return our filtered location data
echo zip_search($zipcode);
wp_die(); // this is required to terminate immediately and return a proper response
}
//Function that contains zip code search functionality
function zip_search($userZip){
$args = array(
'posts_per_page' => -1,
'post_type' => 'Locations'
);
$wp_query = new WP_Query($args);
if( $wp_query->have_posts() ): while( $wp_query->have_posts() ) : $wp_query->the_post();
$zipField=get_field('zip_codes_services');
$zipString = $zipField . ', ';
$array = explode(', ' , $zipString); //split string into array seperated by ', '
foreach($array as $value) //loop over values
{
if($value==$userZip){
$post_id = get_the_ID();
$permalink=get_permalink($post_id);
return ($permalink); //print
}
}
endwhile;
wp_reset_postdata();
endif;
}
Lastly I created a separate js folder containing the below scripts.js seen below, for now I just wanted it to redirect to an example site if my form is not blank. Right now the only thing that happens when I submit a zipcode into the form is the page refreshes.
$("form#zipcode").on("submit", function(event) {
$('form#zipcode .clear-button').addClass('active');
event.preventDefault();
zipcode_search(zip_search_filter());
});
function zipcode_search(zip_search_filter) {
//add ajax loader
$("form#zipcode .ajax-content-loader").addClass("active");
//process the form
$.ajax({
type: "POST", // define the type of HTTP verb we want to use (POST for our form)
url: ajaxcall.ajaxurl,
data: {
action: "locations_search", //calls the function in the functions.php file
zip_search_filter: zip_search_filter
},
success: function(response) {
//redirect to new page
if (response != "") {
alert("You will now be redirected.");
window.location = "http://www.example.com/";
}
//remove the loader
$("#zipcode .ajax-content-loader").removeClass(
"active"
);
}
});
return false; //prevents the form from submitting to a new page.
}
Does anyone have experience with AJAX calls in Wordpress, any advice is appreciated.
It sounds like the form is submitting before your functions are called. Try moving event.preventDefault() so it is called first, like so:
$("form#zipcode").on("submit", function(event) {
event.preventDefault(); //call this first
$('form#zipcode .clear-button').addClass('active');
zipcode_search(zip_search_filter());
});
Check your syntax, =! should instead be !=;
//correct syntax
if (data != "") {
alert("You will now be redirected.");
window.location = "http://www.example.com/";
}
Also, your success function returns response, but you are referencing data. Change the code so that the proper object is referenced:
success: function(response) {
//redirect to new page
if (response != "") {
alert("You will now be redirected.");
window.location = "http://www.example.com/";
}
or...
success: function(data) {
//redirect to new page
if (data != "") {
alert("You will now be redirected.");
window.location = "http://www.example.com/";
}
First I had to add a form id:
Then I made a number of edits, in functions.php :
/**
* LOCATION SEARCH FILTER AJAX
*
* call location search filter ajax
*
* #return ajax json data via function.
*/
add_action( 'wp_ajax_locations_search', 'prefix_ajax_locations_search' );
add_action( 'wp_ajax_nopriv_locations_search', 'prefix_ajax_locations_search' ); //used for handling AJAX requests from unauthenticated users
function prefix_ajax_locations_search() {
// Handle request then generate response using WP_Ajax_Response
$zipcode = $_POST[ 'zipcode' ];
//return our filtered location data
echo zip_search($zipcode);
wp_die(); // this is required to terminate immediately and return a proper response
}
//Function that contains zip code search functionality
function zip_search($userZip){
$args = array(
'posts_per_page' => -1,
'post_type' => 'Locations'
);
$wp_query = new WP_Query($args);
if( $wp_query->have_posts() ): while( $wp_query->have_posts() ) : $wp_query->the_post();
$zipField=get_field('zip_codes_services');
$zipString = $zipField . ', ';
$array = explode(', ' , $zipString); //split string into array seperated by ', '
foreach($array as $value) //loop over values
{
if($value==$userZip){
$post_id = get_the_ID();
$permalink=get_permalink($post_id);
return ($permalink); //print
}
}
endwhile;
wp_reset_postdata();
endif;
}
I also had to include my custom jquery file and my AJAX file in the enqueue_scripts function functions.php:
wp_enqueue_script( 'custom-js', get_stylesheet_directory_uri() . '/js/scripts.js', array('jquery'), '', true );
wp_localize_script( 'custom-js', 'ajaxcall', array('ajaxurl' => admin_url( 'admin-ajax.php' )));
Finally in scripts.js I made the following changes and instead of redirecting to http://example.com I redirected to the permalink I get from my zip_search function seen above.
/*
* Put all your regular jQuery in here.
* Within this funtion you can use the namespace $ instead of jQuery
* ex. use this $('#id') ... NOT jQuery('#id')
*/
jQuery(document).ready(function($) {
$("form#zipcode").on("submit", function(event) {
event.preventDefault();
$('form#zipcode .clear-button').addClass('active');
//get the entered zipcode value to pass through our function.
var zipcode = $(this).find('input[name="zipcode"]').val();
zipcode_search(zipcode);
});
function zipcode_search(zipcode) {
//add ajax loader
$("form#zipcode .ajax-content-loader").addClass("active");
//process the form
$.ajax({
type: "POST", // define the type of HTTP verb we want to use (POST for our form)
url: ajaxcall.ajaxurl,
data: {
action: "locations_search", //calls the function in the functions.php file
zipcode: zipcode
},
success: function(response) {
//redirect to new page
if (response != "") {
//alert("You will now be redirected.");
window.location = response;
}
//remove the loader
$("#zipcode .ajax-content-loader").removeClass(
"active"
);
}
});
return false; //prevents the form from submitting to a new page.
}
}); /* end of as page load scripts */
Doing all of this solved my problem and the search form now works how I need it to.
I am new to website development and am developing a WordPress site. Although similar to another question on SO, that question does not use jQuery.AJAX but rather jQuery.post with a request type of 'category'. I have some sort of syntax problem when trying to use AJAX. I have created a simple plugin to enter a name, send it to the server, and have it echoed back. Following is the php file, my-ajax-test.php:
add_action( 'wp_enqueue_scripts', 'ajax_test_enqueue_scripts' );
function ajax_test_enqueue_scripts() {
wp_enqueue_script( 'my-script-handler', plugins_url( '/my-ajax-test.js', __FILE__ ), array('jquery'), '1.0', true );
wp_localize_script( 'my-script-handler', 'ajax_test', array(
'ajax_url' => admin_url( 'admin-ajax.php' )
));
}
function my_ajax_test() {
/**** Create Input Form ****************************/
?>
<h2>Select Persons You Wish to Register</h2>
<form action="">
<input type="text" id="ajax_guest_name" name="guest_name">
<p id="ajax_guest_text">Enter Guest Name</p>
<br><br>
<input type="button" id="ajax_rsvp" name="ajax_guest" value="Register Guest">
</form>
<?php
add_action( 'wp_ajax_my_ajax_callback', 'my_ajax_callback' );
function my_ajax_callback() {
$guest_name = $_POST[ajax_guest_name];
echo $guest_name;
die();
}
};
add_shortcode('My-AJAX-Test', 'my_ajax_test');
The JS file, my-ajax-test.js looks like this:
// use wordpresses version of script
var $jq = jQuery.noConflict();
$jq(document).ready(function(){
$jq("#ajax_rsvp").click(function(){
/* Send guest name to server via AJAX */
var g_name = document.getElementById("ajax_guest_name").value;
alert("RSVP Button was clicked with Guest Name: " + g_name);
$jq.ajax({
url : ajax_test.ajax_url,
type : 'post',
data : {
action: 'my-ajax-test',
ajax_guest_name : g_name
},
success:function(data) {
// This outputs the result of the ajax request
console.log(data);
},
error: function(errorThrown){
console.log(errorThrown);
}
}); // End of AJAX function
}); // End of button click function
}); // End of Main Document Ready Function
All seems well, but nothing is being sent to the server with the button click. The Console log has an error:
HTTP400: BAD REQUEST - The request could not be processed by the server due to invalid syntax.
(XHR)POST - http://localhost:81/wordpress/wp-admin/admin-ajax.php
I keep going over the code to see what I have wrong and can not find it. Any suggestions would be appreciated.
Hello LCSF and welcome to StackOverflow.
You have multiple errors in your code. You are posting your data to a my-ajax-test function (which doesn't exist. Your main plugin function is my_ajax_test) when what you should be doing is posting it to your my_ajax_callback function. That is the function you registered via the wp_ajax action hook. That is why Wordpress cannot find you action. In addition to that, your callback function is encapsulated inside your main plugin function, which is why even if you change the Ajax request the function will not be found due to it's scope. To solve this do the following:
In your JavaScript file change the action in your Ajax function to my_ajax_callback
Extract the my_ajax_callback function out of the my_ajax_test function. Your code structure will then look like this:
function my_ajax_test(){
//content
}
add_action( 'wp_ajax_my_ajax_callback', 'my_ajax_callback' );
function my_ajax_callback(){
//content
}
Action my-ajax-test is not what you need to pass as action parameter.
Replace:
action: 'my-ajax-test',
with:
action: 'my_ajax_callback',
I'm new to wordpress and i wanted to try using ajax calls for some mouse click events.
I have some basic code to test if it works.
In my plugin file plugin.php
function my_scripts() {
$plugin_url = plugin_dir_url( __FILE__ );
wp_register_script('search-filter',$plugin_url . 'js/search-filter.js',array(), filemtime( plugin_dir_path( __FILE__ ) . 'js/search-filter.js' ));
wp_localize_script( 'search-filter', 'my_ajax_call', array( 'ajax_url' => admin_url('admin-ajax.php')) );
wp_enqueue_script( 'search-filter');
}
add_action( 'wp_enqueue_scripts', 'my_scripts' );
function myAjaxHanlder(){
var_dump("THIS IS A TEST");
echo '<script>console.log("MY AJAX HANDLER")</script>';
}
add_action('wp_ajax_hello_world', 'myAjaxHanlder' );
add_action('wp_ajax_nopriv_hello_world', 'myAjaxHanlder' );
and in my javascript file search-filter.js
(function($){
$(document).ready(function(){
$(".search-hits").click(function(e){
e.preventDefault();
// var gender = $("#gender").val()||[];
// var brand =$("#brand").val() || [];
// var color =$("#color").val() || [];
// var gender_JSON = JSON.stringify(gender);
$.ajax({
type: 'POST',
dataType: 'json',
crossDomain : true,
url: my_ajax_call.ajax_url,
data: {action:'hello_world', query:"nike"},
success: function(response){
alert(response);
}
});
});
});
})(jQuery);
I'm able to send the data using ajax, but the function myAjaxHanlder is not getting executed.
I think you're approaching it incorrectly, and WP handles Ajax differently. Your Ajax handler function should be included in both hooks (for the admin and front-end) like so:
add_action('wp_ajax_hello_world', 'hello_world' );
add_action('wp_ajax_nopriv_hello_world', 'hello_world' );
The handler function name has to be used on your Ajax call as well (which you've done):
data: {action:'hello_world' ...
It also has to echo a response and then die. I recommend using WP's implementation of die() :
wp_die();
Here is what I reworked, hopefully it helps:
function hello_world(){
var_dump("THIS IS A TEST");
echo '<script>console.log("MY AJAX HANDLER")</script>';
// OR
echo $_POST['query'];
wp_die();
}
add_action('wp_ajax_hello_world', 'hello_world' );
add_action('wp_ajax_nopriv_hello_world', 'hello_world' );
Codex has more info: Ajax on WP Plugins
I added the following to my functions.php file:
add_action('wp_ajax_send_email', 'send_email_callback');
add_action('wp_ajax_nopriv_send_email', 'send_email_callback');
So i added the following callback function:
send_email_callback()
{
//do some processing
echo json_encode(array('response'=>'Ya man it worked.'));
//return control back to *-ajax.php
}
This is what is returned to my javascript :
{"response":"Ya man it worked."}0
So ofcourse when it reaches the $.parseJSON( msg ) line I get Uncaught SyntaxError: Unexpected number.
var request = $.ajax({
url: "/wp-admin/admin-ajax.php",
method: "POST",
data: { action : 'send_email', P : container },
dataType: "html"
});
request.done(function( msg ) {
var obj = $.parseJSON( msg );
console.log(obj.response);
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
});
So where does this 0 come from? admin-ajax.php
it says on line 97:
// Default status
die( '0' );
Why is this here, why am I reaching the die('0') line? Shouldnt it be just die() so it doesnt mess up my response?
Seems the only way to fix this is either modify admin-ajax.php or simply die() at the end of my send_email_callback() function.
In WordPress AJAX actions, you aren't supposed to return the response, but echo the response and call die yourself. WordPress will continue to call all of the AJAX registered callbacks until one of the callbacks kills the execution, with the final one dieing with the response of 0.
Example from WordPress Codec AJAX in Plugins
<?php
add_action( 'wp_ajax_my_action', 'my_action_callback' );
function my_action_callback() {
global $wpdb; // this is how you get access to the database
$whatever = intval( $_POST['whatever'] );
$whatever += 10;
echo $whatever;
wp_die(); // this is required to terminate immediately and return a proper response
}
I'm trying to load a .js file from a wp plugin.
The code where I load jquery, jquery-UI and my .js file look like this, and is located inside the "main" plugin file:
//Load Java and Jquery
function load_jquery() {
// only use this method is we're not in wp-admin
if (!is_admin()) {
// deregister the original version of jQuery
wp_deregister_script('jquery');
wp_deregister_script('jquery-ui');
wp_deregister_script('lyox-script');
// discover the correct protocol to use
$protocol='http:';
if($_SERVER['HTTPS']=='on') {
$protocol='https:';
}
// register the Google CDN version
wp_register_script('jquery', $protocol.'//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js', false, '1.10.2');
wp_register_script('jquery-ui', $protocol.'//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js', false, '1.10.3');
wp_register_script('lyox-script', plugins_url( '/includes/script.js' , __FILE__ ), array( 'jquery', 'jquery-ui' ) );
// add it back into the queue
wp_enqueue_script('jquery');
wp_enqueue_script('jquery-ui');
wp_enqueue_script('lyox-script');
}
}
add_action('template_redirect', 'load_jquery');
Then inside the .js file I have the following code, where the post() function is added to a form button onclick="post();":
$(document).ready(function() {
function post() {
var name = $('#name').val();
$.post('process.php', {postname:name},
function(data)
{
alert(data);
$('#result').html(data);
});
}
});
Still nothing happens when I try it out on a page. Any ideas?
You can do like this using admin ajax :
I will not explain the functions . you can google it and learn .
Step 1: Localize some values for your script to be used in your javascript files,
get admin-ajax.php url
$author_nonce = wp_create_nonce( 'nk_author' );
wp_localize_script( 'nk_script', 'nk_object',array( 'nk_ajax_url' => admin_url( 'admin-ajax.php' ) , 'nk_plugin_url' => plugins_url() ,'nk_author' => $author_nonce) );
step 2 : In your script you can do this .
var data = {
action: 'nk_action', // the function that will be called in your plugin
_ajax_nonce : nk_object.nk_author, // nonce for security
id : 'mydata' //your data to be sent
};
//(admin ajax url , your data , callback for response )
jQuery.post(nk_object.nk_ajax_url, data, function(response) {
$('#nk_result').html(response);
}
});//end jQuery.post
step 3 : In your plugin.php file do this
<?php
add_action('wp_ajax_nk_action', 'nk_action_callback');
function nk_action_callback() {
check_ajax_referer('nk_author');
if(isset($_POST['id']))
{
$id=$_POST['id'];
echo $id;
}
die();//dont forget to write die
}?>