jQuery and Ajax in WordPress Plugins – Administration Pages

This is a quick overview of how to use jQuery and its Ajax functions in WordPress. To get the point across, I’ll use a simple and contrived example. We’ll have an admin screen with a list of categories. Clicking on the name of one of the categories will fetch a list of titles of posts in that category and display them as a sub-list of that category.

Step 1: Build the Admin Page

Zipping right by the details of how to add an admin page, here’s the code for adding our category list as a management page.

In category-list.php:

Plugin Name: Category List
Description: A list of categories.
Author: Jonathan Brinley
Author URI: http://xplus3.net/
function category_list_add_management_page(  ) {
  if ( function_exists('add_management_page') ) {
    $page = add_management_page( 'Category List', 'Category List', 'manage_categories', 'category_list', 'category_list_admin' );
function category_list_admin(  ) {
  $categories = get_categories( 'orderby=name&hierarchical=0&hide_empty=0' );
add_action('admin_menu', 'category_list_add_management_page');

In category-list-view.php:

<div class="wrap">
  <h2>Category List</h2>
  <ul id="category_list">
  < ?php foreach ( $categories as $cat ): ?>
    <li id="cat-<?php echo $cat->cat_ID; ?>" class="category-name"><a href="#">< ?php echo $cat->cat_name; ?></a></li>
  < ?php endforeach; ?>

Step 2: Add the Ajax Response

As mentioned above, clicking on a category will fetch a list of post titles. So we need a function that builds that list. We’ll add this function to category_list.php:

function category_list_posts(  ) {
  $catID = isset($_POST['catID'])?$_POST['catID']:null;
  if ( $catID ) {
    $posts = get_posts( "numberposts=-1&post_status=publish,pending,future,private,draft&category=$catID" );

And, of course, we need posts_list_view.php:

<ul class="posts_list">
< ?php foreach ( $posts as $post ): ?>
  <li class="post-name post-<?php echo $post->ID; ?>">< ?php echo $post->post_title; ?></li>
< ?php endforeach; ?>

We also need to tell WordPress when to call this function, using another action hook:

add_action('wp_ajax_category_list_posts', 'category_list_posts' );

Whenever you post a request to wp-admin/admin-ajax.php with the action parameter of category_list_posts (this being everything after “wp_ajax_” in the action hook), WordPress will call category_list_posts(), the function named in the second parameter of add_action.

Note the call to die at the end of category_list_posts(). When responding to Ajax requests, WordPress will end the response by calling die('0'). If you don’t want that “0” to appear at the end of your response, you have to call die before WordPress gets a chance.

Step 3: Write Your JavaScript

You have your list of categories, and your function that will return the list of posts in a category. Now you need some JavaScript to put them together.

Remember that the Ajax request needs to be sent to wp-admin/admin-ajax.php. Without knowing what directory your plugin will be installed in, nor the full path to wp-admin, you need to provide the URL to your JavaScript somehow. The easiest way I see it to change the href attribute of your links to that URL. So in category_list_view.php, well replace the opening anchor tag with:

<a href="<?php bloginfo('wpurl'); ?>/wp-admin/admin-ajax.php"></a>

With that, we can create a simple JavaScript file (we’ll call it category_list.js):

jQuery(document).ready( function($) {
  $("li.category-name a").click( function() {
    var li = $(this).parent();
    /* only fetch results once */
    $(this).unbind('click').bind('click', function(){return false;});
    $.post($(this).attr("href"), {
        action: "category_list_posts",
        catID: li.attr("id").substr(4)
      }, function(data) {
    return false;

This posts data to the given URL, and appends the response to the end of the li.

Now we just need to tell WordPress to include the JavaScript when we’re on the Category List page. Back up in category_list_add_management_page, we’ll make use of that $page variable we set up earlier. Add a line after that:

add_action("admin_print_scripts-$page", 'category_list_scripts');

And add the category_list_scripts function to specify which scripts to add:

function category_list_scripts(  ) {
  wp_enqueue_script( "category-list", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/category_list.js"), array( 'jquery' ) );

This plugin doesn’t really do anything useful, but if you want to see the full source code, you’re welcome to download it.

12 thoughts on “jQuery and Ajax in WordPress Plugins – Administration Pages”

  1. Thanks, exactly what I needed to figure out the admin side of ajax in WP. I think the example if a bit convoluted with all the split up files and there was no need for that for the purposes of keeping it simpler. Nonetheless, thank you.

  2. I agree with Artem. It took me some time to figure it out but I have it up and running now. Do you mind if I publish another tutorial on my site with a more cleaner example?

    But thanks anyway, It was a great help.

  3. Too good!

    I came here from the codex page on using AJAX in plugins. Your post was much easier to understand than the admin section of the codex page!

    I also disagree with the comments above about splitting your views into different files. It may be a small example, but it’s still nice to see an example of good design discipline. :)

  4. Community service! Great article, got my plugin running with jquery in no time at all. Thanks!

  5. Good tutorial, but it still leaves out some minor details that could have someone mislead for a while. For starters the source code that you can download includes code that is needed for the demo to work correctly and that code is not mentioned at all in the tutorial.

    Remember the point of a tutorial is to inform possible viewers / users ways to accomplish a task at either a simple or complex level. So when writing a tutorial make sure that all necessary points are covered ( depending of the complexity level of the task to be accomplished ) or you may run the risk of further confusing or misleading a fellow developer.

Comments are closed.