Last updated February 21, 2014. Created by EdgarPE on September 8, 2008.
Edited by drupalshrek, rkeppner, dddave, darrenwh. Log in to edit this page.

Ajax 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 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:

<?php
/**
* 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(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 (Drupal 7):

(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) {
        var result = Drupal.parseJson(response);
        $('div.field-type-image div.field-item').html(result.data);
    }
})(jQuery);

Here's what our JavaScript will look like (Drupal 6):

Drupal.behaviors.myModule = 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) {
    var result = Drupal.parseJson(response);
    $('div.field-type-image div.field-item').html(result.data);
}

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.

Also worth noting: in Drupal 6, you wrap all your module’s jQuery behaviors in a function assigned to Drupal.behaviors.myModule; there's no need to call it within $(document).ready() as Drupal automatically does it for you; all behaviors can then be reattached to DOM elements that have come from an AJAX call. For more information on this look at the Drupal JavaScript API documentation

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

Thanks for posting this. It helped a lot to help me ajaxify my site.

I've wrote a short but helpfull (I hope :) ) step by step tutorial to show how to set up a module that handles ajax requests.

I hope it helps other people, as I found it hard to find something similar elsewhere.

Do you have a working demo of your implemented tutorial?

But if you need any help, please let me know here or by sending me an email via my website

I wouldn't mind an example of what mymodule_get_photo() looked like. I'll be doing the same thing but for any given node type. Basically I'd like to wind up with a fully rendered node sans-theme to dump into a div.

--
eric

Is there any similar ajax tutorials for Drupal 7?

The best way to learn D7 Ajax is to download the D7 examples suite of modules at drupal.org/project/examples and look at the Ajax Example module.

I would disagree. I found the above explanation much easier to understand than trying to figure out the Example module, which, as extensive as it seems, was entirely lacking application to my own use cases.

There's just no substitute for explaining the basics.

--
Tom/* Ogden

I just realised that I do this way too little: thanking people for their efforts.

So hence: Thanks for this very clearly written tutorial!

Made our live much easier.

What if you want to pass parameters in the .get() function in JavaScript, where would they be available on the PHP side?

Naresh Kosgi

for arguments, you can simply pass them like this:

$.get('/photos/get/photos/arg1/arg2/', null, imageDetails);

then in php you can access them with:

// you will probably need to put different numbers in the arg() function, but you get the idea.
$arg1 = arg(1);
$arg2 = arg(2);

I see something not related to the question but it may interest some people. The javascript in the sample will only work if the drupal is installed on the root of the server. You can use Drupal.settings.basePath to have something which should work everywhere:

$.get(Drupal.settings.basePath+'photos/get/photos/'+ parseInt(this.id, 10), null, imageDetails);

David Mignot
www.idflood.com
gittip

Thanks so much for the Drupal.settings.basePath tip. It helped save me some time :)

If you do not want to pass the parameters as part of the url
i.e. module/function/arg/arg2

you could simply access them from your drupal function using php's good old $_GET super global.

$arg = $_GET['arg']
$arg2 = $_GET['arg2']

I have a block with a view that displays comments. The view takes an nid from the page it resides on as an argument, also it is being refreshed using the views refresh module from a comment form on the page. The comments also paginate using ajax and so far everything is fine. Also on the same page is a video player with a playlist. Each video in the site is assigned to its own node, and I want people to be able to comment on each video as the player goes through them in the playlist. So using the api and customizing the playlist I am able to capture the nid associated with each video using JS. What I would like to do but cannot seem to wrap my head around, is to pass this nid to the comment block ( I will use js and the dom to modify the form so it updates the right node) so that when the video changes the comment block changes as well. I have tried writing this string to the div ID:

currLink = "/views/ajax?view_name=comments&view_display_id=block_1&view_args=1360&view_path=node%2F1360&view_base_path=null&view_dom_id=1&pager_element=0";
$('#block-views-comments-block_1').load(currLink);

I got this from watching my live header when I did a test comment. The 1360 is the nid. But that just gives me this

{ "status": true, "display": "\x3cdiv class="view view-comments view-id-comments view-display-id-block_1 view-dom-id-1"\x3e\n      \x3cdiv class="views-admin-links views-hide"\x3e\n      \x3cul class="links"\x3e\x3cli class="0 first"\x3e\x3ca href="/admin/build/views/edit/comments?destination=node%2F1360%3Fview_name%3Dcomments%26view_display_id%3Dblock_1%26view_args%3D1360%26view_path%3Dnode%252F1360%26view_base_path%3Dnull%26view_dom_id%3D1%26pager_element%3D0#views-tab-block_1"\x3eEdit\x3c/a\x3e\x3c/li\x3e\n\x3cli class="1"\x3e\x3ca href="/admin/build/views/export/comments"\x3eExport\x3c/a\x3e\x3c/li\x3e\n\x3cli class="2 last"\x3e\x3ca href="/admin/build/views/clone/comments"\x3eClone\x3c/a\x3e\x3c/li\x3e\n\x3c/ul\x3e    \x3c/div\x3e\n    \n  \n  \n      \x3cdiv class="view-empty"\x3e\n      \x3cp\x3ePost comments above!\x3c/p\x3e\n    \x3c/div\x3e\n  \n  \n  \n  \n  \n  \n\x3c/div\x3e ", "title": "Comments", "__callbacks": [ "Drupal.Views.Ajax.ajaxViewResponse" ], "messages": "" }

in the target block. I know I am close, could anyone tell me what step I am missing? To be clear I have everything working up until the actual changing of the comment view. Sorry if this is a common question, I have searched through the site and read just about every ajaxy article I could find, there is just something I am missing here and I don't know what it is. Thanks for your help!

I got the comment view refreshed by using the following code:

function sendCommentAjax(nid){
var target = ".view-dom-id-1";
var currLink = "/views/ajax?js=1&page=1&view_name=comments&view_display_id=block_1&view_args="+nid+"&view_path=node%2F"+nid+"&view_base_path=null&view_dom_id=1&pager_element=0";
$.ajax({
                url: currLink,
                type: 'GET',
                //data: nid,
                success: function(response) {
                  if (response.__callbacks) {
                    $.each(response.__callbacks, function(i, callback) {
                     $('.ajax-form').removeClass('ajax-form').addClass('ajax-form-temp');
                      eval(callback)(target, response);
                      $('.ajax-form-temp').addClass('ajax-form');
                    });
                  }
                },
                error: function() { alert(Drupal.t("An error occurred at @path.", {'@path': ajax_path})); },
                dataType: 'json'
              });
}

Now I need to make another ajax call that refreshes the form block so that its action is:
/comment/reply/1360

I tried just replacing the action with
var actionUrl = "/comment/reply/"+nid;
$('#comment-form').attr("action",actionUrl);

But I guess that doesn't jive with all the hidden element tokens. So how would I go about refreshing this form so I can submit comments to the newly refreshed view? Using the Comment Block module on this. Hope this helps someone else and maybe I can be shown the light on the rest. Also if this is the wrong way to go about this I am all ears (or eyeballs I guess in this case).

Remember to disable and then re-enable your module after you implement hook_menu. If you don't then Drupal will not recognise that they exist and you'll get a white screen when trying to access the url.

...of disablind and re-enabling module. Just cleaning menu cache using "administrator menu" module is enough.

where is Drupal.attachBehaviors in the example ?

The above example doesn't work if the clean url is disabled.
what would be the best way to handle if clean url is disabled.

Hi, Best way to handle non clean urls is :

function sendCommentAjax(nid){
var target = ".view-dom-id-1";
var currLink = "/views/ajax?js=1&page=1&view_name=comments&view_display_id=block_1&view_args="+nid+"&view_path=node%2F"+nid+"&view_base_path=null&view_dom_id=1&pager_element=0";
$.ajax({
                url: Drupal.settings.basePath + "?q=currLink",
                type: 'GET',
                //data: nid,
                success: function(response) {
                  if (response.__callbacks) {
                    $.each(response.__callbacks, function(i, callback) {
                     $('.ajax-form').removeClass('ajax-form').addClass('ajax-form-temp');
                      eval(callback)(target, response);
                      $('.ajax-form-temp').addClass('ajax-form');
                    });
                  }
                },
                error: function() { alert(Drupal.t("An error occurred at @path.", {'@path': ajax_path})); },
                dataType: 'json'
              });
}

Hope this helps.

Need help ?
Reach me on skype : sag_13684

Share your Posts, Url, Sites
www.sociopost.com

I have just about got the problem solved but the last step is driving me nuts! Partly because I know there has to be a simple solution for it. Basically I have this string:

\x3cform action="/comment/reply/1360"  accept-charset="UTF-8" method="post" id="comment-form" class="ajax-form"\x3e\n\x3cdiv\x3e\x3cdiv class="form-item"\x3e\n \x3clabel\x3eYour name: \x3c/label\x3e\n \x3ca href="/users/testuser1" title="View user profile."\x3etestuser1\x3c/a\x3e\n\x3c/div\x3e\n\x3cdiv class="form-item" id="edit-comment-wrapper"\x3e\n \x3clabel for="edit-comment"\x3eComment: \x3cspan class="form-required" title="This field is required."\x3e*\x3c/span\x3e\x3c/label\x3e\n \x3ctextarea cols="60" rows="15" name="comment" id="edit-comment"  class="form-textarea required"\x3e\x3c/textarea\x3e\n \x3cdiv class="description"\x3eComments are limited to a maximum of \x3cem\x3e200\x3c/em\x3e characters.\x3c/div\x3e\n\x3c/div\x3e\n\x3cul class="tips"\x3e\x3cli\x3eWeb page addresses and e-mail addresses turn into links automatically.\x3c/li\x3e\x3cli\x3eAllowed HTML tags: \x26lt;a\x26gt; \x26lt;em\x26gt; \x26lt;strong\x26gt; \x26lt;cite\x26gt; \x26lt;code\x26gt; \x26lt;ul\x26gt; \x26lt;ol\x26gt; \x26lt;li\x26gt; \x26lt;dl\x26gt; \x26lt;dt\x26gt; \x26lt;dd\x26gt;\x3c/li\x3e\x3cli\x3eLines and paragraphs break automatically.\x3c/li\x3e\x3c/ul\x3e\x3cp\x3e\x3ca href="/filter/tips"\x3eMore information about formatting options\x3c/a\x3e\x3c/p\x3e\x3cinput type="hidden" name="form_build_id" id="form-b7bde2234f6776c650943e6084269b36" value="form-b7bde2234f6776c650943e6084269b36"  /\x3e\n\x3cinput type="hidden" name="form_token" id="edit-form-token" value="b2f7e36a7e76afee64a195a7a7f12251"  /\x3e\n\x3cinput type="hidden" name="form_id" id="edit-comment-form" value="comment_form"  /\x3e\n\x3cinput type="submit" name="op" id="edit-submit" value="COMMENT"  class="form-submit ajax-trigger" /\x3e\n\x3cinput type="submit" name="op" id="edit-preview" value="Preview"  class="form-submit ajax-trigger" /\x3e\n\n\x3c/div\x3e\x3c/form\x3e\n

which I need to convert to this:

<form action="/comment/reply/1360"  accept-charset="UTF-8" method="post" id="comment-form" class="ajax-form"> <div><div class="form-item">  <label>Your name: </label>  <a href="/users/testuser1" title="View user profile.">testuser1</a> </div> <div class="form-item" id="edit-comment-wrapper">  <label for="edit-comment">Comment: <span class="form-required" title="This field is required.">*</span></label>  <textarea cols="60" rows="15" name="comment" id="edit-comment"  class="form-textarea required"></textarea>  <div class="description">Comments are limited to a maximum of <em>200</em> characters.</div> </div> <ul class="tips"><li>Web page addresses and e-mail addresses turn into links automatically.</li><li>Allowed HTML tags: &lt;a&gt; &lt;em&gt; &lt;strong&gt; &lt;cite&gt; &lt;code&gt; &lt;ul&gt; &lt;ol&gt; &lt;li&gt; &lt;dl&gt; &lt;dt&gt; &lt;dd&gt;</li><li>Lines and paragraphs break automatically.</li></ul><p><a href="/filter/tips">More information about formatting options</a></p><input type="hidden" name="form_build_id" id="form-b7bde2234f6776c650943e6084269b36" value="form-b7bde2234f6776c650943e6084269b36"  /> <input type="hidden" name="form_token" id="edit-form-token" value="b2f7e36a7e76afee64a195a7a7f12251"  /> <input type="hidden" name="form_id" id="edit-comment-form" value="comment_form"  /> <input type="submit" name="op" id="edit-submit" value="COMMENT"  class="form-submit ajax-trigger" /> <input type="submit" name="op" id="edit-preview" value="Preview"  class="form-submit ajax-trigger" />  </div></form>

so i wrote this function to do it :

function unjsEncode(string){
var newstring = string.replace("/\n/", " " );
newstring = newstring.replace("/\x3e/", ">");
newstring = newstring.replace("/\x3c/", "<");
newstring = newstring.replace('/"/', '"');
return newstring;
}

But it does not work.
Regex has never been a strong suit of mine, so I am sure I am missing something simple, but of course this was due yesterday. I would appreciate any tips you could give me and I promise to post the whole code either here or in a new article when I am done.

I spent so much time trying to figure out why it was coming out like that. However, I figure it out, make sure you specify the dataType received and do not add any context. In this case you are receiving JSON so make datatype: 'json' when calling the module functions. Hope that helps.

$.ajax(url: 'get/articles/x', datatype: 'json' , etc....);

First, thank you for the tutorial!

It looks like Drupal JavaScript API documentation is a broken link.

Cheers

Try this other url

http://drupal.org/node/304258

This is the site I crash often: http://www.drupalfever.com

Hi,
I have this error while loading the page from pager where ajax loads the page...
How to solve this problem.. please help.. Its urgent .Am new to drupal and php..
Thanks all
{"status":true,"data":"\u003cdiv style=\"clear:both;\"\u003e\u003c\/div\u003e\u003cdiv class=\"page\" style=\"position: relative;\"\u003e\u003c\/div\u003e\u003c\/div\u003e"}