Smashing Newsletter

There are a lot of “without-page-refresh” solutions out there, but here’s one you can create with AJAX. In this tutorial, you can learn how to build a simple plugin which will allow readers to send a report without reloading the page.

If you have ever wanted to send a form without reloading the page, provide a look-ahead search function that prompts the user with suggestions as they type, or auto-save documents, then what you need is AJAX (also known as XHR). A behind-the-scenes request is sent to the server, and returning data to your form. Whenever you see a loader animation after you have made some action on the page, it’s probably an AJAX request being submitted to the server.

In this article, I’m going to guide you through the entire process of creating and handling AJAX calls. You will learn not only how to make an AJAX call, but also how to do it the best way using features that WordPress offers developers right out of the box. We will build a simple plugin which will allow readers to send a report to the administrator with information about any bug they may spot on your website.

A user comes across a bug and clicks the “Report a Bug” button. As a result, the form for a message is presented. Clicking on the button a second time will send the user to the administrator.

At the end of the article, you can download the working example and examine the code in full.

Let’s dig in!

AJAX

“Without reloading the page” is the key sentence here. AJAX stands for Asynchronous JavaScript And XML because initially, the data returned from the server is supposed to be in XML. However, it’s easier to send them in JSON, which JavaScript likes more.

We are going to use AJAX to send an email. You cannot do it from the front-end, so you have to call the back-end. Usually, we would send a POST request to the server, handle it and redirect the user back to the page with the form. In this iteration, we don’t want to reload the page. Instead, we are calling the backend directly where we’re going to capture the form data with JavaScript, then send an asynchronous request to the server to handle the response.

There are three things which WordPress AJAX needs to work — five of them to work well. These are:

Object for the AJAX action

JavaScript script

WordPress action

Protection

Error handling

Let’s take a closer look at each of them.

Object

Our object is the form. This is our thing to handle with JavaScript. I started with creating a file with header needed by WordPress plugin and putting an empty object inside. In the end, I’m creating a new instance of the plugin’s class.

Even though I’m using some OOP here, we are not going to utilize any advanced practices. The code would work just as well when written procedurally with separate functions. But objects within WordPress plugins have one advantage: You don’t have to prefix your functions — only the class name has to be unique.

Let’s display our form to the users. We are going to hook into the the_content filter and embed the form at the end of every post. In class’ constructor I added the filter:

I’m also using the wp_localize_script function to pass the translated button label to JS. We don’t have any gettext functions in JavaScript, so we have to do it here. This function will create the settings object which can be accessed directly from our script.

In our script, we are going to listen for a button click. Once that happens we will show the textarea and switch the button class to listen for the second click which is sending the form.

AJAX Requests To WordPress

To send an AJAX request, you really need only one-and-only parameter: the requested URL. WordPress has the special file for AJAX, so we don’t have to create our own. It’s /wp-admin/admin-ajax.php.

As long as we are in the wp-admin area, this file URL is available in JS in the ajaxurl variable. On the front-end, we have to pass this variable on our own. Luckily we already used the wp_localize_script function, so we can just add another key to it:

We are listening for a click on class we switched on the button before.

As you can see, I’m changing the button text to “…” Why? Because it’s good practice to show the user that something is happening. AJAX requests depend on the server performance and will take some time. Maybe 30ms, but maybe also 3 seconds. If after clicking the button there seems to be no effect, most likely the button will be clicked a second time. This would duplicate the request because as you now know, these are asynchronous.

Next up, I’m creating the data object. This contains all the variables which will be sent to the server callback. The WordPress admin-ajax.php file requires the action property. This has to be unique unless you want the other plugin to handle your requests. The remainder of the parameters is optional. I’m sending the post ID and the report message from textarea.

We then are calling the $.post method. Next, you guessed it; it’s sending the POST request. It’s a shorthand method, but you can use $.ajax method as well, which has more options. As a first parameter we have to pass our handler file URL, then the parameters and then the success callback function. This is the place where we are handling the response. For now, we are just sending the simple message to the browser’s console.

Sending AJAX request to back-end

We are ready to handle the request on the back-end.

WordPress Action

You may be wondering how do we hook into the admin-ajax.php. With action, of course! WordPress has two action types:

wp_ajax_nopriv_{$action}
wp_ajax_{$action}

Where the $action is, the action name passed in AJAX params. It’s send_bug_report in our case.

First of these actions will be executed only for not logged-in users. The second one only for logged-in users. So if you want the request to be handled for both, you have to define both. This is what I’ve done in the class’ constructor:

The most important part in terms of handling AJAX in WordPress is the last function - wp_send_json_success which prints the JSON encoded output and dies. All we need to grab the response with AJAX success callback. It has also a twin brother, wp_send_json_error, but we’ll get to that part later.

The object from these functions has two properties:

successIs a boolean and depends if you call it success or error function.

dataIf you provide the parameter for the function.

That’s all from on the back-end side. Let’s handle the response in JS.

We are going to remove the button and textarea and display a message returned from the server in the container we prepared before:

To validate the request we have to regenerate the input string, so I’m using the post_id key sent from AJAX. The second parameter is the key in the $_REQUEST array. Third controls the automated wp_die if nonce is not matching.

I don’t want it to die itself. Instead, I’m catching the result of this function and sending JSON error in a nice object.

You may also notice the usage of the sanitize_text_field function in email message parameter. This is just to make sure user will not send any harmful scripts or HTML.

Lastly, we need to wrap the AJAX success callback in JS in if statement to check if the request was successful:

Button Protection

You know that user can click the button second time, before AJAX will finish the call. But there’s one simple trick which will block the second click - disabling the button. So after the click, I’m going to block it and unblock it after getting the response:

Error Handling

Validation

What if the user tries to send an empty message? I don’t want to be bothered with such emails. Let’s block these attempts with validation techniques.

In JS I’m going to add a simple validation, to show the user that something went wrong. If the message is empty the user will see the red border around the textarea. If a message is present there, we are restoring the neutral border:

As you see we have used the wp_send_json_error function twice, but there’s no need to display unique messages for users. Instead, passing the exact error description, I’m going to add another key to our script settings object which will cover both errors:

I hope this gives you a nice foundation for your own “without-page-refresh” solutions. You can do this to all the forms on your website. It’s also a great way to optimize any heavy piece of the website which doesn’t have to be loaded right away, such as a big list of products in a drop-down. You can load them via AJAX just after clicking on the drop-down — it’s that simple.

The possibilities are almost limitless. Let me know in the comments what your ideas are!