Ajax in Drupal using jQuery

Last updated on
16 July 2021

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

Ajax (Asynchronous JavaScript And XML) is a particular type of functionality that enables your pages to retrieve and display information from a resource on the server without the need to reload. jQuery provides a few different Ajax commands, depending on your exact requirements. Here is the simplest Ajax call you can make with jQuery:

$('#someDiv').load(url);

What this is saying is "Find the div with the id of 'someDiv' and load the html that you find at the location 'url' into this div".

(Technical aside: Actually, this example is really AHAH (Asynchronous HTML and HTTP)and not Ajax, because it returns straight html and does not need to be parsed. On the other hand, Ajax, in its strictest sense, retrieves XML data from a server resource, which then needs to be parsed before being displayed on your page. But in fact, very few Ajax applications actually return XML data these days. A much more common format for data to be sent back from the server is JSON. And this is how we do it in Drupal.)

The jQuery utility functions below provide for the extra flexibility you need when dealing with data coming back from the server that needs to be parsed.

$.get(url, parameters, callback);
$.post(url, parameters, callback);
$.ajax(options);

The only difference between $.get and $.post is the http request method used to send your parameters (an array passed as the second argument) to the server. Very often in Drupal, you won't need to send any parameters because the url you will be calling will be a menu callback you have set up as, for example, 'ajax/get/node_details' taking one argument, 'nid' and so you would simply make the call to 'ajax/get/node_details/123' and not need to send your nid parameter as a parameter in the second argument.

So, here's a very simple example of how this would work. Suppose you have a slideshow page on your site, similar to what you often see on news sites, where underneath the main image are numbered buttons and clicking on these instantly changes the image displayed, without reloading the page. Well, to set up something like this you would first of all set up the page so that it outputs a container for the first image (for the purposes of this example we'll assume it loads the first image as normal; also, all images are nodes) and then all the required numbered buttons. Then, to add some ajax action, you'll need to build a custom module that defines your ajax callback. Set up a menu callback in your .module file, something like this:

/**
 * Implements hook_menu().
 */
function mymodule_menu() {
  $items['photos/get/photos'] = array(
    'page callback' => 'mymodule_get_photos_ajax',
    'type' => MENU_CALLBACK,
    'access arguments' => array('access content'),
  );
  return $items;
}

/**
 * Callback to return JSON encoded image for given nid.
 */
function mymodule_get_photos_ajax($nid) {
  $photo = mymodule_get_photo($nid); // returns the filepath of my photo
  $image = theme('image', $photo);
  drupal_json_output(array('status' => 0, 'data' => $image));
}

Our JavaScript is going to make a request to the path photos/get/photos/123, where 123 is the nid of the photo it's looking for, and the function mymodule_get_photos_ajax() will take that nid and do the required php to be able to send back the image path in a JSON object, to be parsed by the JavaScript.

Here's what our JavaScript will look like:

(function($) {
    Drupal.behaviors.myModule = {
        'attach': function(context) {
            $('a.photo_button:not(.mymodule-processed)', context)
                    .addClass('mymodule-processed')
                    .bind('click', function() {
                $.get('/photos/get/photos/' + parseInt(this.id, 10), null, imageDetails);
                return false;
            });
        }
    }

    var imageDetails = function(response) {
        $('div.field-type-image div.field-item').html(response.data);
    }
})(jQuery);

The first function here is binding the ajax behaviour to the onclick event of all buttons with the class "photo_button". It's using $.get, meaning it will make a http GET request to the path passed in as the first argument. Notice that it's getting the nid of the required node by parsing the id of the button - an easier way would have been to make the href of the button the ajax path itself but that would have nasty results for users without JavaScript. So the href is just going to go to the node and the JavaScript retrieves the nid by other means. We pass in null as the second argument because we don't need to pass in any additional parameters, we're already sending the nid in the url. And finally we specify the callback function, imageDetails, to be called when the request has been successful. The imageDetails function parses the JSON object that our PHP function has sent back and loads the 'image' portion of the result into our container div.

Help improve this page

Page status: No known problems

You can: