Drupal Tutorials

Getting going with AHAH and Drupal 6

You should have a good understanding of Drupal 6 and be interested in learning more about the form API and Drupal development in general.
In my opinion one of the best things added to Drupal 6 was the AHAH (or Asynchronous HTML and HTTP) framework, so in this lesson I'm going to give you a quick overview of how to use it.

What is AHAH and what can it can do?

Wikipedia sums it up well:
AHAH, is a method for updating webpages dynamically using Javascript, similar to Ajax, but with the difference that the response from the request is used directly without parsing on the clientside. This means that server responses need to be text or already include valid XHTML/HTML structure.
Basically when a user performs an action (like clicking a link or form button) AHAH can respond to this action by calling a URL and returning the URLs respond(HTML or text) without needing to refresh the whole page.

The upload module uses AHAH to allow uploading of images and files without needing to refresh the other page.
Upload module example

How it works

The AHAH framework is fully integrated into Drupal 6 so all you need to do is hook into it using Drupals form API. Here's an example of how to make the form API to use AHAH.
<?php
  $form
['my_form_submit'] = array(
   
'#type' => 'submit',
   
'#value' => t('Submit'),
   
'#weight' => 1,
   
'#submit' => array('my_form_submit'),//none JS version
   
'#ahah' => array(
     
'event' => 'click',
     
'path' => 'mymodule/js',
     
'wrapper' => 'myform-wrapper',
     
'method' => 'replace',
     
'effect' => 'fade',
     
'progress' => array(
       
'type' => 'bar',
       
'message' => t('Loading...')
      )     
    ),
?>
We're focusing on the #ahah array at the end of the form array, let me explain the various parameters one by one:
  • #ahah['event']

    This is the type of event that must be perform on the $form item (in this example the Submit button) in order for the AHAH behaviour to be triggered.

    Possible values: 'click', 'blur', 'change' (Optional will default to click)

    Examples: user clicking a button (click) or user selecting a value in a drop down menu (change)
  • #ahah['path']

    This is the menu item or URL that is called when the "event" has been triggered. Without this AHAH will not be triggered.

    In the above example you would need to have a coresponding menu item defined in your hook_menu like so:
    <?php
    function mymodule_menu() {
     
    $items['mymodule/js'] = array(
       
    'page callback' => 'mymodule_js',
       
    'access arguments' => array('access mymodule js'),
       
    'type' => MENU_CALLBACK,
      );
      ...
      return
    $items;
    }

    /**
    * callback function for mymodule/js
    * The return HTML will be outputted by AHAH
    */
    function mymodule_js() {
      return
    drupal_json(array('status' => TRUE, 'data' => "Hello Drupal World"));;
    }
    ?>
    It's important the you use the drupal_json function so that Javascript can understand the returned values/HTML.

    Alternatively you could use the AHAH helper module which can handle all the menu definitions for you.
  • #ahah['wrapper']

    This is the ID of the HTML element on the current page that should be updated with the returned HTML from our #ahah['path'] defined menu path.

    In our example 'wrapper' => 'mymodule-wrapper' corresponds to <div id="mymodule-wrapper">.....</div> and this div would display the "Hello Drupal World" text returned by our mymodule_js() menu function when AHAH has been triggered.
  • #ahah['method']

    This is how you want the HTML returned from our #ahah['path'] menu function to be attached to our #ahah['wrapper'] defined wrapper.
    By default it with replace the HTML currently in the wrapper with the new HTML, but you can also have the follow:

    'after' = Insert returned HTML after the wrapper element
    'append' = Append returned HTML to the inside of our wrapper element.
    'before' = Insert returned HTML before our wrapper element.
    'prepend' = Prepend returned HTML to the inside of our wrapper element.
  • #ahah['effect']

    This is the jQuery effect you want to apply to the wrapper element when it receives the new HTML from our menu function.

    Possible values: 'none' (default), 'fade', 'slide'.
  • #ahah['progress']

    This is the type of animation you want to display while the user is waiting for the AHAH menu function to response. It can either be a progress bar or a throbber icon and you can also add an optional message too.

    progress bar
    Throbber

    The #ahah['progress'] value should be an array of settings (see example above). Here are the full parameters:

    #ahah['progress']['type'] = Type of animation to display, bar or throbber
    #ahah['progress']['message'] = An optional message that should be displayed with the progress bar or throbber. You should wrap the text in the t().
    #ahah['progress']['url'] = An optional URL to a menu item that determines how full the progress bar is.
Ok, that was all pretty theory heavy so here's a diagram to help illustrate how the AHAH workflow works: AHAH workflow

An example

Right, lets quickly go over a real life example of where AHAH is already used in Drupal. For this we're going to look at the poll module that is shipped as part of Drupal 6 core.

The poll module uses AHAH on the poll creation page to allow users to add more choices to a poll question.

In the poll_form function the following code declares that AHAH should interact with the "poll_more" form item:
<?php

//AHAH declaration in poll_form function
$form['choice_wrapper']['poll_more'] = array(
 
'#type' => 'submit',
 
'#value' => t('More choices'),
 
'#description' => t("If the amount of boxes above isn't enough, click here to add more choices."),
 
'#weight' => 1,
 
'#submit' => array('poll_more_choices_submit'), // If no javascript action.
 
'#ahah' => array(
   
'path' => 'poll/js',
   
'wrapper' => 'poll-choices',
   
'method' => 'replace',
   
'effect' => 'fade',
  ),
);
?>
This states that the poll/js menu should be called when AHAH is triggered so the module must define a menu item for this like so:
<?php
function poll_menu() {
  ..... 
 
$items['poll/js'] = array(
   
'title' => 'Javascript Choice Form',
   
'page callback' => 'poll_choice_js',
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );
  ......
}
?>
As you can see the menu item calls a function called poll_choice_js, so now let's see what that does:
<?php
function poll_choice_js() {
 
$delta = count($_POST['choice']);

 
// Build our new form element.
 
$form_element = _poll_choice_form($delta);
 
drupal_alter('form', $form_element, array(), 'poll_choice_js');

 
// Build the new form.
 
$form_state = array('submitted' => FALSE);
 
$form_build_id = $_POST['form_build_id'];
 
// Add the new element to the stored form. Without adding the element to the
  // form, Drupal is not aware of this new elements existence and will not
  // process it. We retreive the cached form, add the element, and resave.
 
if (!$form = form_get_cache($form_build_id, $form_state)) {
    exit();
  }
 
$form['choice_wrapper']['choice'][$delta] = $form_element;
 
form_set_cache($form_build_id, $form, $form_state);
 
$form += array(
   
'#post' => $_POST,
   
'#programmed' => FALSE,
  );

 
// Rebuild the form.
 
$form = form_builder('poll_node_form', $form, $form_state);

 
// Render the new output.
 
$choice_form = $form['choice_wrapper']['choice'];
  unset(
$choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers.
 
$choice_form[$delta]['#attributes']['class'] = empty($choice_form[$delta]['#attributes']['class']) ? 'ahah-new-content' : $choice_form[$delta]['#attributes']['class'] .' ahah-new-content';
 
$choice_form[$delta]['chvotes']['#value'] = 0;
 
$output = theme('status_messages') . drupal_render($choice_form);

 
drupal_json(array('status' => TRUE, 'data' => $output));
}
?>
This is quite a complex callback function which is beyond the scope of this tutorial but this function basically creates a new form item for an extra choice, renders the form item and then returns it to AHAH via the drupal_json function.

Poll Example
To see this in action simply enable the poll module and go to yoursite.com/node/add/poll.

Woow, that's it! Hopefully this tutorial has shown you how useful AHAH is and got you wanting to try it out! Thanks for reading, comments and questions below.

Commenting on this Tutorial is closed.

Categories:

Comments (25)

xcf33's picture

Great tutorial, I wish the code example could have been more introductory. In any case since AHAH is more advanced it would be appropriate.

The key in the code sample is that when you are calling an AHAH drupal menu function as your form submission handler, you can’t use &$form_state which is part of the form API. Instead you will have to look for values in the $_POST array, using the form id, form_build_id and any value passed in to process the form.

Cheers!

Thanks for this article, is very helpfull.

Mike,
——-
email extractor software

Great article…....BTW, Was there any event can trigger the jQuery function if needed after AHAH update the content of the wrapper??? Thanks in advance.

Excellent site, keep up the good work my colleagues would love this. I read a lot of blogs on a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say I’m glad I found your blog. Also, like to add that i make money on the internet with my drupal blog.Thanks

FBFurnace's picture

Very nice. I like Drupal and have been using it to build a few sites. It’s good for a lot more than for exmaple a classic blog like WordPress =) Thanks for this, fat burning furnace and fat burning furnace review

I love Drupal. I have used Drupal to build a few websites and really like it. There is a lot of flexibility.

Thanks. some great information here keep up the good work.I cannot really leave a more constructive comment as i’m abit out of my deph but i will be checking back here for further updates.Resort MortgageFree Automated Trading Software

Thanks for the information.

Vitiligo

YoungInnovations Pvt. Ltd.'s picture

Nice for a quick start, I have a question,the siteurl/poll/js is not accessible directly when typed in the browser but function when called from the code, how is it done? I read the code of poll_choice_js – function in poll module but there is no obvious way it was done.. can anyone help???

Geshan Manandharhttp://www.geshanmanandhar.comblog @ http://geshan.blogspot.com

Hey thanks for this post on AHAH and Drupal 6. Love the name. It looks very interesting but has anyone looked at the security of it? It seems like it could leave people open to XSS or various client side injection attacks?

Inner Game | Seduction Community.

Another great tutorial for starters although I think AHAH is already advanced.

Farmville

Awesome post! Interesting info to know.

Jones,
graphic designers melbourne

Have had enough with Vitiligo? Don’t Give up your hope too soon. Our medically proven Vitiligo Treatment will make you live your life all over again. It’s easy, It’s safe and It’s quick… Have the best Vitiligo Cure at: (http://www.curevitiligooil.com)

Thanks for this post. It really helps to have these tutorials especially when you are newbie.

Critical Illness

Hi..Just registered. Great post. Can’t wait to check out the rest.

Kevin Costner Movies
http://KevinCostnermovies.org/
Kevin Costner Movies

Very useful info. Hope to see more posts soon!

Jones,
cheap banners

Very useful info. Hope to see more posts soon!

Josh,
SEO

Top post. I look forward to reading more. Cheers

monitor stands

Great guidance there on AHAH! I am still getting to grips with Drupal, but these articles are certainly helping a great deal! Many thanks.

Ryan @ Gangster Fancy Dress

addition of AHAH to the Drupal is a major milestone for the community. with AHAH, the developer can build more powerful applications. this is a good tutorial for beginners.

www.interactivemediadegree.net
www.healthsciencesdegrees.com

I am really glad after reading this post as it provides good basic knowledge of AHAH and how it is useful for Drupal. Its to get more knowledge from posts like these
http://www.theyarelocal.com/articles/index.php

I didn’t know its a method for updating webpages dynamically using Javascript.Very good tutorial for the newbies like me. I shared al this post to digg and twitter.
Logo Design

AHAH is a great development philosophy but based on the user comments, i think that the whole framework is rather confusing. with HTTP component hidden by the higher layers, i wonder how many programmers will find the motivation to directly code to that level. i mean higher levels of code were developed specifically to hide the complexities of direct HTTP programming.

Online Political Science degrees

myinsurancemaster's picture

Drupal is one of the best Content Management Systems (CMS). It is written in PHP and requires a MySQL database. Its basic installation can be easily turned into many different types of web sites – from simple web logs to large online communities. :D :D
Myinsurancemaster

XS Media's picture

this is a awesome post,
but can you give the proper format like which will saved by which name???
since i’m a learner so facing problem to understand this please help me….....
i want to use drupal features in my these sites..
Servicemasters
Realestatezing
I want to thank you for this superb read!! I certainly enjoyed every little bit of it.
I have bookmarked your site to check out the latest stuff you post.
Nightlifeblues