How the D7 AJAX framework could fall short of being spectacularly useful

With a title like that I should start by stating unequivocally that the D7 AJAX framework is a wonderful thing. Based on Earl Miles' CTools AJAX framework, it takes the agony out of dynamic form elements that characterised D6 AHAH forms, and I co-presented a session with Rob Loach and Randy Fay extolling its virtues at DrupalCon SF.

The framework abstracts out all of the common types of functionality we like to achieve with AJAX and gives us access to them using a very simple syntax. By adding the #ajax property to a form element, for example, you can provide a set of instructions for achieving a dependent dropdown or an "Add more choices" button. Here's what that might look like:

$my_form_element = array(
  // ... various element properties
  '#ajax' => array(
    'callback' => 'my_ajax_callback',
    'method' => 'append',
    'effect' => 'slide',

That's quite similar to the #ahah property in D6, but the beauty of it is that your ajax callback is now a very simple affair, just requiring specification of which part of the form to return.

Now, we are used to form elements being defined as arrays of properties, but in Drupal 7 all of the output of our modules should be structured arrays, as per the new Render API. For example, you can now render a link as follows:

  $mylink = array(
    '#type' => 'link',
    '#title' => t('Click here'),
    '#href' => 'node/1',
    '#id' => 'my-link',

That can be passed through drupal_render() and the requisite html will be output. The huge advantage this system has over the way things work in D6 is that all of this output can be altered by other modules before it even gets to the theme layer.

So now, given that links are rendered in a very similar way to form elements, we can just add the #ajax property to our link and the content at its href will be delivered via AJAX, right?

Wrong. The Render API (RAPI) and the AJAX framework were developed completely independently of each other, and when the latter came in, the main challenges core developers were faced with were to do with making it and the Form API play nicely together. However, as we all know, there's more you can do with AJAX than render dynamic form elements. Think of tabbed content on a page for example (always my favourite example) - a series of links on a page which when clicked become 'active' and deliver some new content while hiding the content of the previously active tab. Or what about the LightBox/Shadowbox effect: click on a link and you get some new content in a nice overlay. Two examples of where you click on a link and get some content delivered via AJAX; not a FAPI element in sight.

The new AJAX framework does of course deal with these use cases. The problem is that it does so in a completely pre-RAPI manner, resulting in - *gasp* - inconsistencies in the API.

Inconsistencies in APIs are of course about as natural as rain on an Irish summer's day so my purpose here is not to rant on about how terrible this is. I'm writing this to see if I can rally the troops of module developers out there who think they might be looking to build AJAX functionality in D7 sites in the future, and point out a couple of patches that, with a few extra eyes on them, might just make it in and make this a wonderfully consistent and - yes, spectacularly useful - AJAX framework.

Part of the problem is often that the core developers are not the ones who are going to come up with crazy use cases for things like an AJAX framework, whereas module developers who are likely to have such use cases are intimidated by core issues and don't get involved. Or not until very late in the day (that'd be me).

Here, at any rate, are a couple of issues that I think all you AJAX-loving module devs out there will really want in:
Make #type 'link' ajaxifiable
AJAX behaviors cannot be bound once on links

Please chime in on the issues, even if it's just to say "We need this, and here's why...", and let's see how much more awesome we can make this already awesome framework.

Apparently people have been

Apparently people have been unable to get past the reCaptcha to post comments here - sorry about that! I've removed it for now. Anyway, Randy Fay says: Don't forget this *hyper-important* issue: Lazy-Load Javascript