AHAH done correctly

netsensei - July 19, 2009 - 13:08
Project:Documentation
Component:Correction/Clarification
Category:task
Priority:normal
Assigned:Unassigned
Status:active
Description

Hi,

I would like to attach a zip file containing two example modules to the Doing AHAH Correctly in Drupal 6 page (http://drupal.org/node/331941). It would be nice if I got a go from some documentation guru and a quick review of my code to make sure it's okay.

AHAH is a confusing topic and it took me the better part of a week to grasp the concepts behind it. The handbook page wasn't very helpful. If you browse through the comments, a lot of questions remain unanswered and some suggestions are downright wrong.

The package contains two modules that demo basic AHAH principles:

A. Button demo module

Demonstrates an implementation of AHAH based on a submit button.

B. Select demo module

Demonstrates an implementation of AHAH based on a select list.

Both modules contain comments which explain what happens through the process.

Package attached to this issue.

AttachmentSize
ahah_example.zip14.69 KB

#1

oboskovic - July 20, 2009 - 11:30

Great examples. I just have to ask you, do you know how to add those 2 select fields to existing form, in ahah_example_select_form_alter?
Cause when I do this:

<?php
  $form
= array();
 
// Set the cache to true to create a $form_state cache on submit
 
$form['#cache'] = TRUE;
?>

I loose all data that have been already in $form.

#2

greg.harvey - July 20, 2009 - 15:56

No time today, but will look at these ASAP. Subscribing to remind me to come back later. =)

#3

asmdec - July 22, 2009 - 21:11

This code works fine with simple forms, but when you have some more fields or required fields some problems happen.

I have a form with 4 fields, 2 hierarquical selects and 2 required textfields (title and body). When the value of first select changes, the second select doesn't update, instead I receive a message to correct the required fields (title and body).

I think that some validations should not happen during AHAH callbacks. How could I disable this validations?

I remove the theme('status_messages') from JSON return and when the form is posted I receive the unecessary messages.

Sorry for my bad english :P

#4

netsensei - July 23, 2009 - 08:01

Well, these are just two textbook examples that show the basic principles behind AHAH.

I suppose you're trying to add AHAH to a node form. Maybe you should check out this handbook page:

http://drupal.org/node/331941

Consider the AHAH cycle it describes. Between steps 4 and 5, you could alter the $form array and set #required on both the title and body fields to FALSE. Maybe that would make it work.

#5

oboskovic - July 23, 2009 - 10:06

I just manage to make it (2 select fields in form_alter) with ahah. I'm close to my deadline (with clients), but I'll give my best to post my solution in next week.

#6

asmdec - July 23, 2009 - 13:05

I'm using the following code to remove the messages and CSS error styles before drupal_json is called.

form_set_error(NULL, '', TRUE); // remove CSS error styles
drupal_get_messages(); // remove all messages

It works, but if I could skip validations instead of just hide them, would be nice :)

#7

asmdec - July 23, 2009 - 14:07

I don't understand how the callback of type_submit button is called on change event of the type select.

Please, anyone could explain?

#8

asmdec - July 23, 2009 - 14:48

Reading "Forms API Quickstart Guide" in "Submitting Forms" I figured it out.

1. A submit function is called only if a submit button was present and exists in the $_POST, and validation did not fail.

The data I was posting to my form was not valid (title and/or body required fields are empty) and the flow was not passing to the type_submit submit function breaking the flow, and the animals_kind select wasn't updated.

#9

asmdec - July 23, 2009 - 14:59

netsensei,

setting the #required attribute of required fields to FALSE, works very nice.

I think that's a missing functionality to skip validations instead of doing this work in all fields that have some validation rule that can cause this effect, right?

#10

netsensei - July 23, 2009 - 18:55

Asmdec,

It's not really a case of "missing" functionality here. AHAH functionality in Drupal provides you with several hooks where you should implement your own code. The problem is that it's not very well documented what you can and can't do.

Altering the #required attribute in the AHAH callback shouldn't pose a security risk (can someone confirm this?) because the data is just copied to the $form_state variable. It's used to repopulate the form when it's re-rendered with the changed elements.

If you would submit your entire form for further processing, you should be getting a validation error when a required field wasn't filled out.

oboskovic,

I saw your form topic but didn't have much time to give you an entire answer. Using form_alter in a seperate module to give existing fields the AHAH attribute would be my strategy too. I would then implement the required submit handlers and the AHAH call to make it all work in this module. You should pay attention to the naming of your functions and the callbacks. It's easy to make a mistake and AHAH is hard to debug.

I saw your comments on http://drupal.org/node/331941#comment-1503260. This code is using the 'wrong' way as Kat Bailey points out. It's changing the form directly in the AHAH call (mymodule_change_flower() function) and that's just, well, plain wrong. The callback is used to get the data into $form_state and call the submit handlers. Changes to the form happen in the mymodule_form rendering form itself. Or in form_alter in your case.

--
Colada | http://www.colada.be

#11

asmdec - July 23, 2009 - 19:57

Netsensei,

I appreciate your help and understand your effort to better document AHAH for developers to know exactly what they're doing. Perhaps I don't use the right word when I say "missing" (bad english :), sorry.

I think that this "missing" functionality is (could be) in Form API, in drupal_process_form more exactly. It would receive some parameters that indicates that validation is not needed.

Hierarquical selects (i.e.) don't need to validate the entire data of the form to populate one element. We're thinking only in #required validator, but we have many other validators that need to be disabled as well, like mail validator, user-defined validators, etc.

In the case of not valid data posted to form, could I call form_execute_handlers('submit', $form, $form_state) after step #5 (drupal_process_form call)?

Sorry if my ideas are confused, I'm learning AHAH these days and I don't have very deep knowledge so.

#12

asmdec - July 24, 2009 - 02:16

I'm having another kind of bug now, the same as (not)discussed in http://drupal.org/node/371339.

1/ im creating a new node
2/ im using ahah to change a value
3/ i submit the form without filling mandatory fields
4/ so i have a new page telling me "missing fields..." and now with the new node form, the main form "action" is set to the ahah submit url

You know any about this??

#13

greg.harvey - July 24, 2009 - 08:06

@asmdec, just do a drupal_get_messages() call after right at the end of your callback function and it will clear out any messages set during the node form validation that don't apply at this point. =)

#14

oboskovic - July 24, 2009 - 09:24

I make 2 files for everyone how needs 2 select fields (like country and city, or category and subcategory), in form_alter(). First file shows an ordinary , custom fields added in some content_type by form_alter function.

And second file shows how to change 2 cck fields into 2 select fields with ahah. More specific , it is a workaround for Hierarchical Select fields in some content type. I had to solve this problem fast, and this was the only solution after 10 days of research. It is not nice, but it works.
I made content type with 2 text fields called: field_category and field_subcategory. I made taxonomy Location, that has depth 2. (I mean it has Countries and Cities items). In form_alert function I made 2 dummy fields called: category and subcategory. They are select fields , and they are made with ahah, to replace Hiearachical select fields. I also didn't give any permission for cck fields, it means, admin is the only one who can see it.
The script works like this: you chose category, then ahah display subcategory for that category, and when you click on save/submit, you trigger JS that puts those values in corresponding cck fields field_category and field_subcategory. This way, drupal insert/edit/update all data by himself (you don't need to write code for that). That is all.
JS on the end of second file should be put in page.tpl.php.

I was in hurry so sorry if there are some minor mistakes.

AttachmentSize
category_subcategory_select_fields.txt 3.51 KB
taxonomy_cck_fields_with_ahah.txt 4.98 KB

#15

netsensei - July 24, 2009 - 10:37

Well I spent an hour or so to fit the code from my select example in a CCK form with hook_form_alter.

I'm faced with the same issues:

* If a required field isn't filled, it complains.
* After an AHAH call, the form action is changed to something else and the data isn't saved in a new node.

I'm going to delve a bit deeper in this and see what I can do to make it work.

--
Colada | http://www.colada.be

#16

asmdec - July 25, 2009 - 20:21

The #action attribute is altered by default form element information provided in hook_elements hook on system module:

<?php
$type
['form'] = array('#method' => 'post', '#action' => request_uri());
?>

request_uri is returning the uri called via AHAH in this case. It happens in drupal_rebuild_form call, wich calls drupal_prepare_form, wich calls _element_info('form'), wich invokes the hook_elements hook and set the #action as the uri requested by AHAH.

I'm setting manually the #action attribute.

<?php
$form
['#action'] = '/path/to/original/action';
?>

#17

creazion_dev - August 18, 2009 - 23:01

Thx. You made my day.

#18

Edward.H - September 27, 2009 - 15:47

thanks,You are a star!

#19

cfmcoder - October 18, 2009 - 08:44

The example code for select works for Firefox, but fails for IE6 and IE7. When the first select is chosen, the second select does not appear. Any ideas?

#20

himerus - November 7, 2009 - 19:57
Title:AHAH done correctly» Some notes on my own implementation

I've noticed a couple things on my own implementation. Some have already been mentioned here.

In order to prevent issues with multiple validations (form validate works once, then the #action url is reset to the callback rather than the correct one, so the #action parameter needs to be manually set using:

<?php
  $form
['#action'] = base_path() .'/path_to_your/page_callback';
?>

Rather than CSS'ing out the extra submit button, it is more appropriate to use #access = FALSE to avoid it rendering. The callback is still registered, and will be used during submission of the select element

<?php
  $form
['theme_submit'] = array(
   
'#type' => 'submit',
   
'#value' => t('Select Theme'),
   
'#access'=> FALSE,
   
'#submit' => array('delta_add_override_select_theme_submit'),
  );
?>

Also, regarding having the validation callbacks called when the AHAH element is submitted, I only found one clean option.
I've avoided using #required = TRUE, even on the fields I do require. What I have done also in my validate callback for the main form is to check to ensure the appropriate button was used for the callback, in most default cases the #id is edit-submit

<?php
function delta_add_override_validate($form, &$form_state) {
 
// only valid when we are truly submitting the form, not for AHAH
 
if ($form_state['clicked_button']['#id'] == 'edit-submit') {
   
$delta = $form_state['values']['delta_override'];
    if (!
$delta['name']) {
     
form_set_error('name', t('You must create a valid <strong>Override Title</strong> for this override.'));
    }
    if (!
$delta['system_name']) {
     
form_set_error('system_name', t('You must create a valid <strong>System Name</strong> for this override.'));
    }
    if (!
$delta['theme']) {
     
form_set_error('theme', t('You need to select a theme for this override to apply to.'));
    }
  }
}
?>

This really is a great piece of documentation. Needless to say the AHAH implementations are confusing at best, and this goes a little way further to a better understanding for myself personally.

I'll say it's not perfect, but it is a BIG step towards a more usable explanation. Thanks for the work!!

#21

himerus - November 7, 2009 - 19:58
Title:Some notes on my own implementation» AHAH done correctly

My bad, accidentally reset title, changing back.

 
 

Drupal is a registered trademark of Dries Buytaert.