AJAX with 6.x FormAPI

by pwolanin - draft based on IRC conversation with Eaton

This page is slightly out of date. For methods for adding JS to forms look at the #ahah documentation:
http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...

Even when using the #ahah form element, the callback function still needs to operate essentially as described below:

AJAX with 6.x FormAPI form (such as a form_alter'd piece of the node form) is, right now, is a theoretical possibility. It's not something that any code explicitly supports with helper functions or what not, but it is now more readily possible than with 5.x.

First, make sure that the form has $form['#cache'] = TRUE; because normally, Drupal doesn't cache the first time a form is shown, only when it's rebuilt for the first time, indicating that it'll probably be looping.

The form build id shows up in a hidden field on the client side. This is easily transformed into a cache id as $cid = 'form_'. $build_id. Then you can get the cached form in your callback, alter it, and save it back to the cache like:

$cache = cache_get($cid, 'cache_form');
$form = $cache->data;

// Alter the form
$form['my-select']['#options'] = $new_options;

$expire = max(ini_get('session.cookie_lifetime'), 86400);
cache_set($cid, $form, 'cache_form', $expire);

In terms of what you need to do to alter the form, the cached form is exactly what would be passed through a normal hook_form_alter function. It's actually cached right after that step.

Note- it is important that any server-side callback does not trust the user input. For example, you should never, ever, take from the client side a comma-delimited list for the new set of options for a select box! A hacker could easily re-write the JS to send options that will endanger your site security.

You'll almost certainly want to send back to the client side the HTML corresponding to the altered element, so that the visible form can be updated by the JS:

note - we're all still a little fuzzy on the best way to do this step. You need to process the form further so that the element you want is ready to be rendered.

$form_state = array();
$form['#post'] = array();
$form = form_builder($form['form_id']['#value'] , $form, $form_state);
$output = drupal_render($form['my-select']);
print(drupal_to_js($output));
exit();

The essential logic of the caching is all in function drupal_get_form(), so look there for guidance.

The form_get_cache() and

yched - December 28, 2007 - 18:06

The form_get_cache() and form_set_cache() functions can take care of handling the 'caching' part.

 
 

Drupal is a registered trademark of Dries Buytaert.