Advertisement
Creative Coding

A Primer on Ajax in the WordPress Dashboard - Requesting and Responding

by

In this two part series, we're taking a look at how to properly introduce Ajax-specific functionality into the WordPress Dashboard.

In the first article in the series, we began working on a plugin that displays a notification as soon as it's activated ... but that's it. In this article, we'll add Ajax-enabled functionality that will allow users to dismiss the message and we'll finish up with a working version of the plugin.

Specifically, we're going to cover all of the things necessary on both the server-side and the client-side that are necessary to process an Ajax request and respond appropriately.

Finally, we'll review a checklist of items that all Ajax-based WordPress functionality should have to make sure that you properly employ the API in future projects.


Remember the Nonce

Before we get started, it's important to make sure that you have the nonce value in the function that renders your notification method. For review, here's the function that we included in the first article:

public function display_admin_notice() {

	$html = '<div id="ajax-notification" class="updated">';
		$html .= '<p>';
			$html .= __( 'The Ajax Notification example plugin is active. This message will appear until you choose to <a href="javascript:;" id="dismiss-ajax-notification">dismiss it</a>.', 'ajax-notification' );
		$html .= '</p>';
		$html .= '<span id="ajax-notification-nonce" class="hidden">' . wp_create_nonce( 'ajax-notification-nonce' ) . '</span>';
	$html .= '</div><!-- /.updated -->';

	echo $html;

}

Notice that we're rendering the nonce value using wp_create_nonce in a span element having the ID of ajax-notification-nonce. I bring this up for three reasons:

  1. Nonce values provide security measures and are important when you're making any type of request from the front-end to the back-end.
  2. In my experience, this is one of the things that developers most often leave out of their work - this is meant to make sure we have this covered prior to writing any additional code.
  3. The element containing the nonce value needs a specific ID so that we can easily access it using JavaScript when initiating our Ajax request.

With that, let's get to writing the Ajax functionality.


On to Ajax

Building Ajax-based functionality in the WordPress Dashboard typically includes four key points:

  • Some JavaScript functionality that will respond to the user's event and send it to the server
  • A server-side callback function that is responsible for managing the request coming from the browser
  • Server-side functionality that will send the data back to the browser
  • JavaScript functionality responsible for handling the response

Though there's no particular order in which we need to write this code, we'll just go down the list as it's stated above and work through it.

Sending the Request

The JavaScript code for sending the request is relatively boilerplate stuff, but we need to first outline what it is that we're actually going to do:

  • The user decides to dismiss the notification
  • The user clicks on the dismiss anchor that we've provided
  • JavaScript responds to the event when the user clicks on said anchor
  • JavaScript sends a request to the server

We'll write the code incrementally to make sure that it's easy to follow along. First, we'll start by setting up the code after the window has loaded and we'll make sure that the Ajax notification message is present:

(function ($) {
	$(function () {

		// Check to see if the Ajax Notification is visible; otherwise,
		// we won't worry about doing any of this.
		if ($('#dismiss-ajax-notification').length > 0) {
			// Stuff TODO here...
		});
	});
}(jQuery));

Next, we need to setup an event handler that will fire once the user clicks on the anchor that we've placed in the notification. For this, we need the ID of the message's element - that is, dismiss-ajax-notification.

Because an anchor's default behavior is to try to navigate to its href attribute, we need to also prevent the default action from occurring.

(function ($) {
	"use strict";
	$(function () {

		// Check to see if the Ajax Notification is visible
		if ($('#dismiss-ajax-notification').length > 0) {

			// If so, we need to setup an event handler to trigger it's dismissal
			$('#dismiss-ajax-notification').click(function (evt) {

				evt.preventDefault();
				// More TODO here...

			});

		} // end if

	});
}(jQuery));

At this point, we're ready to actually send the request to the server. To do this, we'll be using the jQuery post function. We'll be passing it three arguments:

  • The URL of the address to which the request should be sent. This is a global value provided by WordPress. It's stored in the ajaxurl variable
  • The hash of options to send to the server. This includes the action - or the function - to fire on the server and the nonce value for validation
  • The function used to handle the response

Let's write out all of this now (including stubbing out the response function) and then we'll hop over to the server-side code.

(function ($) {

	$(function () {

		// Check to see if the Ajax Notification is visible
		if ($('#dismiss-ajax-notification').length > 0) {

			// If so, we need to setup an event handler to trigger it's dismissal
			$('#dismiss-ajax-notification').click(function (evt) {

				evt.preventDefault();

				// Initiate a request to the server-side
				$.post(ajaxurl, {

					// The name of the function to fire on the server
					action: 'hide_admin_notification',

					// The nonce value to send for the security check
					nonce: $.trim($('#ajax-notification-nonce').text())

				}, function (response) {

					// TODO response handler

				});

			});

		} // end if

	});
}(jQuery));

Recall earlier that I said we'd need to know the ID of the field containing the nonce value - that is, ajax-notification-nonce. Notice above that we're grabbing the text value of that element and sending it to the server as the value of the nonce key.

The second thing to notice is that we're sending along an action key that has the value of hide_admin_notification. This is a function that we need to write on the server as it's what will be responsible for actually hiding the notification.

Handling the Request

In our plugin file, we need to create a function that has the name as the action value mentioned above: hide_admin_notification.

As usual, I like to talk about what the function is going to do before writing any code. In this case, here's what needs to be done:

  • We need to make sure the incoming nonce is correct; otherwise, we don't want to execute any code
  • We need to update the option that we created in the first article to set the dismiss to false
  • We need to send a value back to the browser so that it can respond appropriately to the function

Here's the code for making that happen:

public function hide_admin_notification() {

	// First, check the nonce to make sure it matches what we created when displaying the message.
	// If not, we won't do anything.
	if( wp_verify_nonce( $_REQUEST['nonce'], 'ajax-notification-nonce' ) ) {

		// If the update to the option is successful, send 1 back to the browser;
		// Otherwise, send 0.
		if( update_option( 'hide_ajax_notification', true ) ) {
			die( '1' );
		} else {
			die( '0' );
		} // end if/else

	} // end if

}

It's relatively simple, isn't it? The key thing to understand is that we're sending the value of '1' in the context of die if the option is successfully updated; otherwise, we send the value of '0'. This will allow us to read the value in the response on the browser to determine how best to respond.

Obviously, if the returned value is 1, then we can hide the notification.

Before hopping back into the JavaScript, we need to make sure that we wire this function up using the appropriate hook. So, in the plugin's constructor, let's add a line for add_action:

add_action( 'wp_ajax_hide_admin_notification', array( &$this, 'hide_admin_notification' ) );

The key thing to note here is that the tag for the function is labeled 'wp_ajax_hide_admin_notification'.

If you're working with Ajax in the WordPress dashboard, then your hook must be added with the wp_ajax_ prefix and it should end with the name of the function.

This is easily the second most important thing I see developers miss when working on Ajax-based code.

From here, we're ready to hop back into the client-side code.

Handling the Response

Finally, we're ready to handle the response. This is easy: If the server responds with a 1, then we'll hide; otherwise, we won't do anything.

Granted, the best practice would be to display an error message or some type of feedback to let the user know that something went wrong, but the main point of the article is to demonstrate Ajax in WordPress so we'll simply change out the class name from updated to error.

Here's what needs to be added to the JavaScript source to handle the response:

function (response) {

	// If the response was successful (that is, 1 was returned), hide the notification;
	// Otherwise, we'll change the class name of the notification
	if ('1' === response) {
		$('#ajax-notification').fadeOut('slow');
	} else {

		$('#ajax-notification')
			.removeClass('updated')
			.addClass('error');

	} // end if

}

And that's really it. The full JavaScript source should look like this:

(function ($) {
	$(function () {

		// Check to see if the Ajax Notification is visible
		if ($('#dismiss-ajax-notification').length > 0) {

			// If so, we need to setup an event handler to trigger it's dismissal
			$('#dismiss-ajax-notification').click(function (evt) {

				evt.preventDefault();

				// Initiate a request to the server-side
				$.post(ajaxurl, {

					// The name of the function to fire on the server
					action: 'hide_admin_notification',

					// The nonce value to send for the security check
					nonce: $.trim($('#ajax-notification-nonce').text())

				}, function (response) {

					// If the response was successful (that is, 1 was returned), hide the notification;
					// Otherwise, we'll change the class name of the notification
					if ('1' === response) {
						$('#ajax-notification').fadeOut('slow');
					} else {

						$('#ajax-notification')
							.removeClass('updated')
							.addClass('error');

					} // end if

				});

			});

		} // end if

	});
}(jQuery));

And the plugin's PHP should look like this:

/*
Plugin Name: Ajax Notification
Plugin URI: http://github.com/tommcfarlin/ajax-notification
Description: An example plugin used to demonstrate the WordPress Ajax API for a companion article on Envato's WPTuts+ site.
Version: 1.0
Author: Tom McFarlin
Author URI: http://tommcfarlin.com
Author Email: tom@tommcfarlin.com
License:

  Copyright 2012 Tom McFarlin (tom@tommcfarlin.com)

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

class Ajax_Notification {

	/*--------------------------------------------*
	 * Constructor
	 *--------------------------------------------*/

	/**
	 * Initializes the plugin by setting localization, filters, and administration functions.
	 */
	function __construct() {

		load_plugin_textdomain( 'ajax-notification', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );

		register_activation_hook( __FILE__, array( &$this, 'activate' ) );
		register_deactivation_hook( __FILE__, array( &$this, 'deactivate' ) );

		add_action( 'admin_enqueue_scripts', array( &$this, 'register_admin_scripts' ) );

		// Display the admin notice only if it hasn't been hidden
	    if( false == get_option( 'hide_ajax_notification' ) ) {
		    add_action( 'admin_notices', array( &$this, 'display_admin_notice' ) );
	    } // end if

	    add_action( 'wp_ajax_hide_admin_notification', array( &$this, 'hide_admin_notification' ) );

	} // end constructor

	/*--------------------------------------------*
	 * Core Functions
	 *---------------------------------------------*/

	/**
	 * Upon activation, add a new option used to track whether or not to display the notification.
	 */
	public function activate() {
		add_option( 'hide_ajax_notification', false );
	} // end activate

	/**
	 * Upon deactivation, removes the option that was created when the plugin was activated.
	 */
	public function deactivate() {
		delete_option( 'hide_ajax_notification' );
	} // end deactivate

	/**
	 * Registers and enqueues admin-specific minified JavaScript.
	 */
	public function register_admin_scripts() {

		wp_register_script( 'ajax-notification-admin', plugins_url( 'ajax-notification/js/admin.min.js' ) );
		wp_enqueue_script( 'ajax-notification-admin' );

	} // end register_admin_scripts

	/**
	 * Renders the administration notice. Also renders a hidden nonce used for security when processing the Ajax request.
	 */
	public function display_admin_notice() {

    	$html = '<div id="ajax-notification" class="updated">';
    		$html .= '<p>';
    			$html .= __( 'The Ajax Notification example plugin is active. This message will appear until you choose to <a href="javascript:;" id="dismiss-ajax-notification">dismiss it</a>.', 'ajax-notification' );
    		$html .= '</p>';
    		$html .= '<span id="ajax-notification-nonce" class="hidden">' . wp_create_nonce( 'ajax-notification-nonce' ) . '</span>';
    	$html .= '</div><!-- /.updated -->';

    	echo $html;

	} // end display_admin_notice

	/**
	 * JavaScript callback used to hide the administration notice when the 'Dismiss' anchor is clicked on the front end.
	 */
	public function hide_admin_notification() {

		// First, check the nonce to make sure it matches what we created when displaying the message.
		// If not, we won't do anything.
		if( wp_verify_nonce( $_REQUEST['nonce'], 'ajax-notification-nonce' ) ) {

			// If the update to the option is successful, send 1 back to the browser;
			// Otherwise, send 0.
			if( update_option( 'hide_ajax_notification', true ) ) {
				die( '1' );
			} else {
				die( '0' );
			} // end if/else

		} // end if

	} // end hide_admin_notification

} // end class

new Ajax_Notification();

Conclusion

You can grab the plugin on GitHub. For reference, be sure to review the following resources:

Related Posts
  • Code
    Plugins
    Distributing Your Plugins in GitHub with Automatic UpdatesSensorsthumbnail
    This article will teach you that, with a little creative coding, you can host your own WordPress plugins in GitHub while still retaining the automatic update feature.Read More…
  • Code
    Scala
    Building Ribbit in ScalaRibbit scala retina preview
    In this tutorial we will implement the Ribbit application in Scala. We'll be covering how to install the Play web framework, a NetBeans plugin for it, and finally the code in Scala. If you are new to Scala, check out this previous tutorial which will help you set up your environment and provides you with a general platform that you can build upon. Even though the essence of Ribbit is to create/send/read Ribbits (our version of tweets), we will spend a large part of this tutorial explaining how Play works, authentication, and persistence. After these are in place, the rest becomes much easier. We will also implement ribbit creation, submission and listing out all ribbits. Following someone, advanced user settings, and direct messages will be an extra assignment for you to complete on your own. I am sure if you manage to follow along with this tutorial and create Ribbit as explained below, these three functionalities will be easily accomplished as homework.Read More…
  • Code
    Creative Coding
    A Look at the WordPress HTTP API: Saving Data From wp_remote_postDiagram http api
    In the previous post in the series, we began working on a small plugin that provided a practical example of wp_remote_post. The thing is, the example was incomplete. Sure, it's nice to see how to make a call using the function and even how to setup a script responsible for receiving the data and returning the data, but it's of little use unless we do anything with it. In this final article in the series, we're going to revisit the plugin that we started with the last article and begin improving it a bit. Specifically, we will... Review what we've done Begin making some changes to the work that we created in the last article Style the presentation with LESS in order to keep some of our newer skills updated Review the arguments accepted by both wp_remote_get and wp_remote_post Finally, all of the work accomplished in this article will be available on GitHub and linked in the conclusion of the article. But before that, let's go ahead and get started.Read More…
  • Code
    Creative Coding
    A Look at the WordPress HTTP API: A Practical Example of wp_remote_postDiagram http api
    In the previous article, we reviewed the previous articles regarding GET requests, the native PHP facilities for making requests, and reviewed WordPress wp_remote_post API function along with the arguments that it offers. In this article, we're going to make use of wp_remote_post such that we're actually able to see it in action. Remember that this - like wp_remote_post - is part of the HTTP API of which there are other functions worth reviewing. But, for now, we're going to put wp_remote_post to work. Specifically, we're going to do the following: When the page loads, we're going to submit some information to a custom script The script will examine the information and return it to our page We'll then display the data on the page Sure, it's a bit of a contrived example but it will give us the experience of creating a separate PHP script that can be used for operations triggered by the use of wp_remote_post. Anyway, for the purposes of this example, we are going to use the PHP $_SERVER collection to log when the user has submitted their preference rather than require that they have logged in. Finally, the source code will be made available on GitHub and accessible at the end of this series in the following article. For now however, let's get started with working on the plugin.Read More…
  • Code
    Plugins
    Integrating Multiple Choice Quizzes in WordPress – Creating the FrontendIntegrating multiple choice quizzes in wordpress
    This is the second part of the series on developing a multiple choice quiz plugin for WordPress. In the first part we created the backend of our plugin to capture the necessary data to store in the database. In this final part, we will be creating the frontend of the plugin where the users can take quizzes and evaluate their knowledge.Read More…
  • Code
    Creative Coding
    A Primer on Ajax in the WordPress Dashboard - Laying the FoundationThumb 1
    Not long ago, Ajax was all the rage - the idea of updating part of a page without actually needing to reload the entire page was awesome, remember? But it's been a few years and now it's practically the standard - it's hard to think about your favorite web application reloading an entire page to complete a task, isn't it? Depending on your background, there are a number of different ways to implement Ajax. In this series, we're going to do a very brief overview of what Ajax is, how it works, and then how to properly use it within the WordPress administration dashboard.Read More…