AJAX in WordPress – not the kind where you load all or part of a page, but the kind where you use admin-ajax to execute an action – was fairly opaque for me when I first tried to implement it. Granted, that was as part of the Customizer, not the easiest thing in the world to come to grips with. However, it seems to me I had to piece together multiple tutorials to get a complete picture, so I thought I’d put out a simple example that still addresses all of the components.
The main idea: admin-ajax.php (view code on Trac) is a file that executes actions. Those actions can do anything, but generally they are either saving information or displaying content. I’ll stick to displaying content.
AJAX being what it is, setting it up requires both PHP and JavaScript files. I think the easiest way to explain it is probably to walk through an example. This is code for a plugin that provides the ability to pop the primary WordPress menu up in a lightbox (in this case Colorbox) from any element to which you give the id “menu-popper”. It relies on jQuery. The plugin is simply called Colorbox Menu, and in fact if you download jquery.colorbox-min.js and stick it in a folder with the following two files, you can use it (though you’ll want some CSS too).
JavaScript (colorbox-menu.js):
PHP (colorbox-menu.php):
So, what is going on here? The script is executing AJAX in the usual jQuery way, with some specifics required by WordPress and/or best coding practices. There are three lines to highlight:
url: colorboxMenu.ajaxurl
This line tells JavaScript where it is making its request, which is the full URL for admin-ajax.php (likely to be the same relative location in most WP installs, but certainly not all). This is an object property whose value will be the actual URL. The value will be provided to the script when the script is enqueued – more when we look at the PHP file. For now just know there are numerous tutorials that tell you the address of admin-ajax is automatically filled in if you put simplyurl: ajaxurl
; this is true on the admin side, but not when the call is made from the front end.action: 'colorbox_menu_display_main_nav',
The only data we are sending in this example is the name of the action we want executed. You will see in the PHP discussion that it is not actually the name the action is registered under, and need not be the name of the PHP function that gets executed.$.colorbox( { html:result, } );
Your action will send back text or html, just as a string. Colorbox lets you tell it the content of the lightbox when it’s called, which is what we are doing here. You could also insert this into an HTML element with, e.g.,.append()
or.html()
.
The PHP file is doing two things: enqueuing and localizing the script, and teaching admin-ajax how to react to the AJAX request. Enqueuing is as usual; you just have to do it before localizing. The remaining noteworthy pieces:
wp_localize_script( 'colorbox-menu', 'colorboxMenu', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
Script localization is the process of swapping out variables for data known at load time, such as the URL of the admin-ajax file. This tells WordPress that within the script enqueued under the handle “colorbox-menu” it needs to replace properties of the objectcolorboxMenu
with the values associated to them in the array given as the third parameter. You need to pass the URL in this way, but you could pass other information as well, as long as it is known/determined by the time of script loading.function colorbox_menu_load_main_nav()
This is the function that will ultimately be called by the user’s click. It needs to do two things: echo any return information, and terminate itself.wp_nav_menu
echos the menu code already so it can be used bare. Anything that needs to be preceded by an echo command in a template file (e.g.home_url
) needs to be preceded by an echo command in this function, and you can simply echo strings as well. I was pleased to discover that echoing a function that would typically be called from within a page and simply close out PHP to print HTML onto the page (such as get_template_part) works perfectly well also.add_action( 'wp_ajax_nopriv_colorbox_menu_display_main_nav', 'colorbox_menu_load_main_nav' );
add_action( 'wp_ajax_colorbox_menu_display_main_nav', 'colorbox_menu_load_main_nav' );
Here we have something seemingly odd. If you look at the admin-ajax.php code, it tackswp_ajax_nopriv_
orwp_ajax_
on to the front of whatever action it is asked to execute, so when you add your action you need to put those prefixes on to whatever action name you sent in your AJAX data parameter. The second input is the name of the function the action calls. This may seem cumbersome, but it allows you to react differently to AJAX calls depending on whether the person who clicked is logged in to the site (wp_ajax_
) or not (wp_ajax_nopriv_
).
There you have it: what information to include, how to get it where it needs to be, and how to name the pieces.