Using AJAX has long been a great way dealing with real-time updates, including, but not limited to – submitting forms without refreshing page. Shortly, AJAX allows you to make asynchronous HTTP requests to a webserver once a web page is already loaded. AJAX stands for Asynchronous JavaScript and XML. It uses JavaScript to send asynchronous request and handle the response from the server. So in this tutorial we are going to learn how to submit form using AJAX in WordPress.
Create Form For Sending Data With AJAX
First of all, let’s create a basic form, which will POST data asynchronously to the server. Good thing is, that WordPress already has simple way of handling AJAX requests. If you used AJAX in the past, then this will be a breeze for you. But that will discussed a little bit later. Now back to creating a form compatible for AJAX request in WordPress:
<form class="wordpress-ajax-form" method="post" action="<?php echo admin_url('admin-ajax.php'); ?>"> <input type="text" name="name"> <input type="email" name="email"> <input type="hidden" name="action" value="custom_action"> <button>Send</button> </form>
As you see, in order to work with WordPress built-in AJAX handling core functionality, we need form to send data to specific URL, generated by admin_url(‘admin-ajax.php’) function, which basically generates an absolute path to admin-ajax.php file on your WordPress installation. Also, we included an hidden input with action name, where the value will a part of the action hook name that will handle the request, as You will se later on.
jQuery Part
Now then, let’s create a js file, where we will specify ajax functionality:
jQuery(document).ready(function($) { $('.wordpress-ajax-form').on('submit', function(e) { e.preventDefault(); var $form = $(this); $.post($form.attr('action'), $form.serialize(), function(data) { alert('This is data returned from the server ' + data); }, 'json'); }); });
If you have been using AJAX previously, then this will be clear to you, otherwise, refer to this link for explanation.
Setup WordPress Function For Handling AJAX Request
Now the most important part is to create a function that will actually handle and process AJAX request. To do that, let’s head to functions.php file, and add it:
add_action( 'wp_ajax_custom_action', 'custom_action' ); add_action( 'wp_ajax_nopriv_custom_action', 'custom_action' ); function custom_action() { // A default response holder, which will have data for sending back to our js file $response = array( 'error' => false, ); // Example for creating an response with error information, to know in our js file // about the error and behave accordingly, like adding error message to the form with JS if (trim($_POST['email']) == '') { $response['error'] = true; $response['error_message'] = 'Email is required'; // Exit here, for not processing further because of the error exit(json_encode($response)); } // ... Do some code here, like storing inputs to the database, but don't forget to properly sanitize input data! // Don't forget to exit at the end of processing exit(json_encode($response)); }
We created a function which will handle the request, and hooked it to a specific action. The action is formed from two parts: wp_ajax_/wp_ajax_noprov_ + custom_action (notice, this is the value specified in form’s hidden input in our form:
<input type="hidden" name="action" value="custom_action">
You may ask, why we use wp_ajax_ and wp_ajax_nopriv_, and what is the difference between these two? wp_ajax_ is used for handling requests from authenticated users, whereas wp_ajax_nopriv_ is for non-authenticated users. So if You don’t have requirements from which type of users allow to send AJAX request, then it is a good idea to use these two actions at the same time.
Keep in mind, that WordPress AJAX action can return one of these values: 0 or -1.
0 is returned if the requested action is not created, and -1 is returned if /admin-ajax.php file is accessed directly in URL.
Further Enhancing Security With Nonce
It is a good idea to use special WordPress security functionality called nonce. WordPress nonce is used for security purposes, preventing from attacks like CSRF (Cross-site request forgery). It is basically a unique to the current request generated token, which is used for sending along with other data in the form. It is then verified in the server-side, when processing the request with submitted data, including the token. In the server-side, it is already known excactly what token is expected to be from the coming request, so if token will be missing, or modified, application will throw an exception.
To use nonce in our previous created form, we can do this:
<form class="wordpress-ajax-form" method="post" action="<?php echo admin_url('admin-ajax.php'); ?>"> <input type="text" name="name"> <input type="email" name="email"> <input type="hidden" name="action" value="custom_action"> <?php wp_nonce_field( 'custom_action_nonce', 'name_of_nonce_field' ); ?> <button>Send</button> </form>
For more information on wp_nonce_field function, refer to this link.
Then, our server-side verification would look like this:
add_action( 'wp_ajax_custom_action', 'custom_action' ); add_action( 'wp_ajax_nopriv_custom_action', 'custom_action' ); function custom_action() { if ( ! isset( $_POST['name_of_nonce_field'] ) || ! wp_verify_nonce( $_POST['name_of_nonce_field'], 'custom_action_nonce') ) { exit('The form is not valid'); } // ... Processing further }
That’s it. You learned how to use AJAX to submit forms in WordPress. Now with the power of JavaScript, You can modify form to add success message on successful form submit, or otherwise an error message on failed submition, or anything else.
Hi…
Thanks for nice article….but it always return 0 in data.
Please give reason and solution for this…Thanks in advance.
Hi Mamta,
Sorry for late response. As I wrote in article, 0 is returned if the requested action is not created, so it’s most likely that you have mispelled the value of hidden input with name “action”, as in the first code example. The value of this input need to be exact as the name of function, that will handle the ajax request.
Hope this helps. Let me know if you need more help.
add_action( ‘wp_ajax_custom_action’, ‘custon_action’ );
contains a typo, must be custom_action, that’s why 🙂
Hi nick,
You are totally right, i have made a mistake there and now it’s fixed, thanks for pointing it out! 🙂
Hi @regularcoder,
What’s the advantage of using `action=””`
over `wp_localize_script( ‘my-ajax-handle’, ‘wp_ajax_script’, array( ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ) ) );`
Thanks.
Hello again @regularcoder,
When I submit a form (contact form) I’m taken to admin-ajax.php where the nonce message is “The form is not valid” (as per the error message).
I don’t see anything in the js that relates to displaying the result on the page that contains the form without refreshing.
Thanks.
Not working for me.
it always return 0 in data.
Great post ! Insightful and very helpful. I agree with what you wisely pointed out there should be a balance of what your audience wants and what you want them to see. I guess there is need to always implement actionable changes that will bring better results. Thanks for sharing this value-packed post
Many Thanks for this great tutorial.
I have copy all code as you given. but problem is that
1) Page go to ” http://localhost/wp/wp-admin/admin-ajax.php ”
2) Give output ” 0 “
if (trim($_POST[’email’]) == ”) {
$response[‘status’] = false;
$response[‘message’] = ‘Email is required’;
}else{
$response[‘status’] = true;
$response[‘message’] = ‘success’;
}
echo json_encode($response);
exit();
Please use
wp_send_json($response);
instead of
exit(json_encode($response));
Thanks. Also look at using wp_send_json_error($response); and wp_send_json_success$response);
Hi. I followed exactly your tutorial. Thanks a lot
However, after submitting the browser opens
../wp-admin/admin-ajax.php
with
“{\”error\”:false}”
it should come to the success function instead. What do I have wrong?
Hello I am building a custom form so as to learn how to create a plugin, I have this code but is not allowing me to insert the data that I type from the form I need to validate all the fields of the form along with the recaptcha you can help me please?
https://pastebin.com/Xk9dWVL2
Hi, I am getting a “400 Bad Request” -error with this. Any ideas what could be causing the problem? I have followed your example fully. Would be great to have this working properly!