Viziontech Software Solutions
Software development is delicate.
We handle it carefully.

Drupal & Ajax - Basic Tutorial

The following tutorial will guide you step by step how to create a quick implementation of Ajax in Drupal. We will dynamically update a page with content we will read from the server without the need to refresh the page. I tried to make it as simple as possible, just to describe the very basic blocks required to implement Ajax. I suggest you take it further and try to implement more complex implementations according to your site's needs.

Let's start...... I was building an e-commerce website based on Drupal 6 & Ubercart the other day, and wanted to ajaxify the way products are being displayed. I wanted the users to be able to select a products category from a list, and based on that selection, to fetch the list of products for that category.
Note: It is recommended that you will be familiar to Drupal module development (A tutorial can be found here).

Step 1 – Create your “Data Module”
In order to be able to return data to the client, we will start by creating a module that will return the data. Let’s name our new module “dynamic_products”. First create a folder for our new module. This folder should be created in your site’s “modules” folder (Usually /sites/default/modules folder). Let’s name it as our module name (i.e. “dynamic_products”). All the files described later in this section, should be created under this folder. Then, create the .info file for our module. This file provides Drupal information about your module, which is necessary to enable it.
More info about creating the .info file can be found here.
We’ll use the following for our .info file:
 
; $Id$
name = "Dynamic Products"
description = "Returns a list of products according to category."
core = 6.x
package = Example Ajax Modules
Copy, pase & save the above code into “dynamic_products.info”. After we have our .info file created, we continue to create our .module file. This file includes the actual server side code.Go ahead and create “dynamic_products.module” file in our module’s folder.
In order to be able to make a call to the server, and fetch some data, we need a menu_hook that will be used to “intercept” the ajax call. The following function will used as our menu_hook:
 
<?php
function dynamic_products_menu() {

  $items = array();

  $items['products/get'] = array(
    'title' => 'Dynamic Products',
    'page callback' => 'dynamic_products_get_by_category_id',
    'access arguments' => array('access dynamic_products content'),
    'type' => MENU_CALLBACK
  );

  return $items;
}
This tells Drupal to intercept all calls to “http://www.example.com/?q=products/get” or http://www.example.com/products/get, and call the dynamic_products_get_by_category_id callback function.
We should now let Drupal know, who has the permissions to use your module. For that, we will implement Drupal's hook_perm().
 
function dynamic_products_perm() {
   return array('access dynamic_products content');
}
More info about setting permissions can be found here.

It is now time to create the callback function that will return the data. For the purpose of this tutorial, we will create a simple list of products. In real life, the data can be a view output, or anything else you need.
function dynamic_products_get_by_category_id($cat_id){
  $items = '';
  switch($cat_id){
    case 12: 
     $items = '<ul><li>Product 1</li><li>Product 2</li></ul>';
     break;
    case 20:
     $items = '<ul><li>Product 3</li><li>Product 4</li></ul>';
     break;  
  }
// create a JSON object. The object will contain a property named “products” that will be set with the $items variable. 
  return drupal_json(array('products'=>$items));
  exit;
}
Our callback function, accepts a single parameter ($cat_id). Depending on its value, a different list is returned.
The function can have as many parameters as we need, and the way Drupal passes the parameters to the function, is by using parts of the Url that is used by our ajax call.

As you remember, earlier we defined the menu_hook function (dynamic_products_menu), and instructed our module to intercept requests made to “http://www.example.com/products/get”.
In order to pass the category id to our callback function, we simply add it to the request url.
So for example, if we want to use the value 12 as the category id, we simply use the following url http://www.example.com/products/get/12.

We’re almost done with our dynamic_products.module file. We will return to it later on, so go on and save it for now.

Step 2 – Create the javascript file
We will now create a javascript file that will include the client side that will make the ajax call. Create a new file in the module’s folder and name it dynamic_products.js. The following code defines a behavior to handle the click event of one of the html elements in our page.
// $Id$
Drupal.behaviors.dynamic_products = function (context) {
  $('a.categoryLink:not(.categoryLink-processed)', context).click(function () {
    // This function will get exceuted after the ajax request is completed successfully
    var updateProducts = function(data) {
      // The data parameter is a JSON object. The “products” property is the list of products items that was returned from the server response to the ajax request.
      $('#divProducts').html(data.products);
    }
    $.ajax({
      type: 'POST',
      url: this.href, // Which url should be handle the ajax request. This is the url defined in the <a> html tag
      success: updateProducts, // The js function that will be called upon success request
      dataType: 'json', //define the type of data that is going to get back from the server
      data: 'js=1' //Pass a key/value pair
    });
    return false;  // return false so the navigation stops here and not continue to the page in the link
}).addClass('categoryLink-processed');
}
Copy, paste and save the above code into the dynamic_products.js file. We are done with the js file.
Step 3 – Load the javascript file
In order for our client side to load the .js file, we need to return and edit our .module file. We will need to use init_hook to load the .js file when our module is initialized. In order to do that, add the following functions to the .module file:
 
function dynamic_products_theme() {
   return array(
      'dynamic_products_javascript' => array(
         'arguments' => array(),
      ),
   );   
}

function dynamic_products_init() {
  theme('dynamic_products_javascript');
}

function theme_dynamic_products_javascript() {
  drupal_add_js(drupal_get_path('module', 'dynamic_products') . '/dynamic_products.js');
}
Save the .module file.

Note:  Remember to enable our new module via the "admin/build/modules" page.

Step 4 – Create the Html
We are almost done now. We only need to create the html in our page that will make the ajax call. To make it simple, let’s create 2 divs one on top of the other. The top div, will include 2 links, one for each category of products. When one of these links is clicked, we will make a request to the server, and load the content from the response to the bottom div.
 
<div id=”topDiv”>
<a class="categoryLink" href="/products/get/12">Cat. 1</a>
<a class="categoryLink" href="/products/get/20">Cat. 2</a>
</div>
<div id="divProducts"></div>
Create your Drupal page, copy and paste the above code, and that’s it. When you view the page, if you will click one of the “categories” links, a call will be made to the server, and the page will display a list of products specific to the category clicked.

For a more advanced related tutorials, please see:


Comments


Page not found

I made a module as your instruction, .module .info .js, MENU_CALLBACK,
and drupal_json something in my callback function,but when I clicked the page link to the page callback address ,it always said "page not found"...
any suggestion.?

Page not found

First, try to type the url for the menu callback in your browser and verify that you get a response from the server. It should return a JSON object.
If you still get "page not found" message, try to re-install the module.

If the problem is not with the server side, try to debug your js with a debugger or with alerts to verify that you refer to the right menu callback.

good luck

thnxxx

thank you for this great tutorial
really it helps me a lot

Can't get this to work

Clicking on the links after creating and installing the module returns no results, am I missing something?

dont forget to print the

dont forget to print the base_path function
products/get/20>Cat.2

I'm unable to get this to

I'm unable to get this to work. When i go to my page and click on the links nothing happens. I've followed this to a tee with a fresh install of 6.15. Am i supposed to give the drupal page with the html code a url of products/get?

Drupal 5 version

Excellent tutorial! I wanted to be able to do this in Drupal 5 and this gave me a great start in understanding the process. Thought I would share my changes that allow this to be done under Drupal 5.

One thing to note is that I had to update jQuery as the default version that comes with Drupal 5 doesn't handle $.ajax (see http://drupal.org/project/jquery_update).

Here are my changes...

dynamic_products.info:


; $Id$
name = "Dynamic Products"
description = "Returns a list of products according to category."
package = Example Ajax Modules

dynamic_products.modules:


<?php
function dynamic_products_menu() {

$items = array();

$items[] = array(
'path' => 'products/get',
'title' => 'Dynamic Products',
'callback' => 'dynamic_products_get_by_category_id',
'access' => user_access('access dynamic_products content'),
'type' => MENU_CALLBACK
);

return $items;
}

function dynamic_products_perm() {
return array('access dynamic_products content');
}

function dynamic_products_get_by_category_id($cat_id){
$items = '';
switch($cat_id){
case 12:
$items = '

  • Product 1
  • Product 2

';
break;
case 20:
$items = '

  • Product 3
  • Product 4

';
break;
}
// create a JSON object. The object will contain a property named “products” that will be set with the $items variable.
print drupal_to_js(array('products'=>$items));
exit();
}

function dynamic_products_theme() {
return array(
'dynamic_products_javascript' => array(
'arguments' => array(),
),
);
}

function dynamic_products_init() {
theme('dynamic_products_javascript');
}

function theme_dynamic_products_javascript() {
drupal_add_js(drupal_get_path('module', 'dynamic_products') . '/dynamic_products.js');
}

dynamic_products.js


// $Id$

if (Drupal.jsEnabled) {
$(document).ready(function(content) {
$('a.categoryLink:not(.categoryLink-processed)').click(function (content) {
// This function will get exceuted after the ajax request is completed successfully
var updateProducts = function(data) {
// The data parameter is a JSON object. The "products" property is the list of products items that was returned
// from the server response to the ajax request.
$('#divProducts').html(data.products);
}
$.ajax({
type: 'POST',
url: this.href, // Which url should be handle the ajax request. This is the url defined in the html tag
success: updateProducts, // The js function that will be called upon success request
dataType: 'json', //define the type of data that is going to get back from the server
data: 'js=1' //Pass a key/value pair
});
return false; // return false so the navigation stops here and not continue to the page in the link
}).addClass('categoryLink-processed');
});
}

Problems with tutorial

Hi I think this tutorial is fantastic but by some reason when I click on a link a new tab is open with the JSON content { "products": "\x3cul\x3e\x3cli\x3eProduct 3\x3c/li\x3e\x3cli\x3eProduct 4\x3c/li\x3e\x3c/ul\x3e" }

Do you know why this is happening?

thanks in advance

Getting printed JSON

Hello Alberto,

I think the reason you see the JSON is because something is wrong with your client side script.
Do you get the JSON object printed after you make the AJAX call?
Do you have “return false;” in you JavaScript after the AJAX call?

Zion

Very good post, thanks a lot.

Very good post, thanks a lot.

priceless

great tutorial- very useful.
for anyone looking for learning pro-drupal-development book has a similar style

Great break down, thank you

Great break down, thank you very much for taking the time to share your knowledge.

Thanks a million

I've been banging my head against a virtual wall for days now, reading,searching,reading but your example has put it all into to place for me. You've opened a very interesting door for me.

thanks a million.
A.

ps quotes and some extra spaces in the html threw me for a while, the following got it working for me.

Cat. 1
Cat. 2

Great Tutorial

That really helped me a lot on my Ubercart dynamic catalog page, using Ajax. Please continue to provide tutorials around this, maybe with more complex scenarios.

Maybe with how you talked about the views being returned instead of the simple list.

Thanks,
Robert

Fantastic, this is just what

Fantastic, this is just what I need. But would you be so kind as to write a tutorial for updating a cck field as well? :D

Thanks!

Very good post, thanks a lot.

Very good post, thanks a lot.

Stellar write-up!

Just wanted to echo what others have said - incredibly helpful and remarkably well written. Thanks SO much!

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters (without spaces) shown in the image.