Let's start with a review for those who have not already drunk the ahah forms framework kool-aid: Ahah forms is a utility for attaching Ajax-style partial page loading to Drupal forms without having to code any javascript. This is similar to Ruby on Rails' link_to_remote tag or form_remote_tag() function. The method I use to declare the binding is a custom extension to the formAPI.
Here is an example from the modified views_ui.module:
<?php
$form['filter']['#ahah_bindings'][] = array (
'selector' => 'input.expose-button',
'event' => 'click',
'path' => 'admin/build/views/build_view_js',
'wrapper' => 'views_wrapper_exposed_filter',
'params' => array ( 'section' => 'exposed_filter' ),
);
?>This example is binding to the Expose button that shows up on every filter that gets added to a view.
selector: This is a CSS style selector that identifies the elements that are being attached to. The cool thing is that this will bind to matching elements as they get dynamically added on to the page. selector (which used to be called class, but jslint showed me the error of my ways) is optional. If it is not specified, ahah_forms will bind to the id of the form element.
event: Currently I am only supporting 'click' and 'change'
path: This is the basePath relative url that gets called when the event occurs. In response, Drupal (or some other source), must return an html fragment suitable for inserting into the page - we are doing Ahah, not super-fancy XML-processing Ajax. This particular path gets mapped by views_ui_menu to the views_ui_admin_build_view_js callback.
wrapper: This is the id of a page element that contains the html to be swapped out. In terms of the DOM, this is the parent of the targeted section (In the views example, this is a div that lives right inside the exposed filter fieldset).
params: This is an option array of name/values that get passed back to the url, along with the rest of the form parameters. In this case, I am using the section value in views_ui_admin_build_view_js to determine which subform to render and pass back.
Here is a super-simple example that show make it all clear (soon to be in the examples folder of ahah_forms as ahah_simple.module).
<?php
function ahah_simple_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'ahah/simple',
'callback' => 'drupal_get_form',
'callback arguments' => array('ahah_simple_page'),
'type' => 'CALLBACK',
'access' => true,
);
$items[] = array(
'path' => 'ahah/simple_js',
'callback' => 'ahah_simple_js',
'type' => 'CALLBACK',
'access' => true,
);
}
return $items;
}
?>All this does is set up two url -> function mappings.
<?php
function ahah_simple_page() {
$form = array();
$form['target'] = array(
'#type' => 'item',
'#value' => "Don't do it!",
'#prefix' => '<div id="target">',
'#suffix' => '</div>',
);
$form['submit'] = array(
'#type' => 'button',
'#value' => t('Click Me'),
'#ahah_bindings' => array (
array(
'event' => 'click',
'path' => 'ahah/simple_js',
'wrapper' => 'target'
)) ,
);
return $form;
}
?>Build a form with just two element. A string, which puts itself inside a wrapper, and a button with an ahah_binding attached. When you click the button, a call goes out to ahah/simple_js, which is mapped to ahah_simple_js, and whatever gets returned replaces the html inside the wrapper 'target'.
<?php
function ahah_simple_js() {
print '<p>No one ever listens.</p>';
}
?>ahah_simple_js does a print vs return, because if you return a string, Drupal will treat it as content and helpfully wrap it inside of the page.tpl.php template.
Any questions?
excellent article! But... if
excellent article! But... if you want to add a new form element inside the wrapper 'target' instead html code (like 'No one ever listens.') in the ahah_simple_js() function, how can you do that? Thanks!
Check out the todo module in
Check out the todo module in the examples directory on how to modify a form array in the ahah response.
ahah form into a content template ( contemplate )
thank you for your great work on the ahah module for drupal. I've already played around with the examples - but I'm wondering if you've also integrated ahah frames into content templates, because my tests weren't successful yet.
I would be great if you could provide me with a simple example of integrating an ahah form into a content template ( contemplate ).
thank you for your help
swap with a form element
i've modified ahah_simple_js to return form elements:
<?phpfunction ahah_simple_js() {
$form['target'] = array(
'#type' => 'item',
'#value' => "No one ever listens."
);
print drupal_render($form);
}
?>
-> no problems, buf if I use:
<?phpfunction ahah_simple_js() {
$form['target'] = array(
'#type' => 'select',
'#options' => array('blabla')
);
print drupal_render($form);
}
?>
I get a warning on next page:
warning: implode() [function.implode]: Bad arguments. in C:\wamp\www\drupal\includes\form.inc on line 618.
What's the matter ?
autocomplete form fields don't work when in if/then statements
I encountered this when creating dynamic ahah form fields. Autocomplete form fields stop working when put into if->then statements. I also tried switch/case and same deal. Weird thing is that when there are 2 of them, one outside the if/then (or switch/case) statements and another inside if/then statements they both work. When standard one is commented out the second one stops working. Any idea what could be the cause? I'm fairly new to Drupal and can't figure it out.
If you can spare a moment could you take a look at my custom module? It creates a hierarchical select type form for dependent continent->country->city selection:
http://drupalbin.com/4721
Thanks in advance for any insights.