I was having trouble getting my form_alters() to be returned with the AHAH response of the form_elements returned when adding another item. It boils down to the following change.
Index: includes/content.node_form.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/includes/Attic/content.node_form.inc,v
retrieving revision 1.7.2.18
diff -u -p -r1.7.2.18 content.node_form.inc
--- includes/content.node_form.inc 10 Feb 2009 22:53:04 -0000 1.7.2.18
+++ includes/content.node_form.inc 27 Mar 2009 20:31:31 -0000
@@ -320,8 +320,6 @@ function content_add_more_js($type_name_
// Build our new form element for the whole field, asking for one more element.
$form_state['item_count'] = array($field_name => count($_POST[$field_name]) + 1);
$form_element = content_field_form($form, $form_state, $field);
- // Let other modules alter it.
- drupal_alter('form', $form_element, array(), 'content_add_more_js');
// Add the new element at the right place in the (original, unbuilt) form.
if (module_exists('fieldgroup') && ($group_name = _fieldgroup_field_get_group($type['type'], $field_name))) {
@@ -330,6 +328,8 @@ function content_add_more_js($type_name_
else {
$form[$field_name] = $form_element[$field_name];
}
+ // Let other modules alter it.
+ drupal_alter('form', $form, array(), $_POST['form_id']);
// Save the new definition of the form.
$form_state['values'] = array();
This allows other modules to alter the entire form instead of just on a element basis, which is how most modules using form_alter() do things, based up on the $form_id and then more criteria. $form[type] or whatever else they want to switch on.
If their form_alter() implementation if given the form_id of 'content_add_more_js' they are never going to be able to detect it and the AHAH response will not include their changes.
Comments
Comment #1
sirkitree commentedComment #2
markus_petrux commentedNot a correct approach, I think. Note that only the affected elements are going to be sent to the AHAH request, so you should NOT alter any other part of the form here.
On the other hand, you can hook_form_alter() against
$form_id == 'content_add_more_js', and here inspect the form elements to see if you need to alter anything. Is there any information missing that you need to pass on to hook_form_alter()? If so, I would rather fix that.Comment #3
sirkitree commentedI originally came across this while working with Popups API's Popups Reference (http://drupal.org/project/popups_reference) which adds a link to add a new node of the valid node types for a node reference through a popup. A feature I'm trying to add to that is to have a link for each node reference field instance instead of just one for the field. However, anytime the node reference is set to multiple and you click the button to add a new field, the form_alter() that popups_reference implements is not returned with the AHAH response.
I understand that any module could start trying to detect
$form_id == 'content_add_more_js'and be able to correctly alter just the element, but I don't think it to be the best solution, or very friendly for that matter. A module developer would always have to keep in mind that someone 'might' want to utilize his general form_alter() through AHAH and take it into account, rather than just having CCK's AHAH callback just be able to handle typical form_alter() code.'Typical' in this case is as I described above; the fact that usually a form_alter() is comprised of the detection of a form id followed by detection of the elements within it in order to alter them. That being said, popups_reference probably needs to change to conform to this slightly better, but I'm still not sure of the value of passing along 'content_add_more_js' as the $form_id. I'm thinking it should probably be the $_POST['form_id'], no? In which case the patch I have above would become:
Comment #4
quinn-2 commentedsubscribing
Comment #5
russbollesjr commentedsubscribing
Comment #6
sradomski commentedThe "correct" approach in Drupal6 is to rebuild the complete form even for AHAH submits, thus invoking drupal_rebuild_form -> drupal_prepare_form -> hook_form_alter as described here:
http://drupal.org/node/331941
I am writing a CCK userreference widget for inline user registration and came across the non-standard invocation of hook_form_alter issue as I need a group of radios across all widgets.
As a quick hack, one can replace $form[$field['field_name']][$field['field_name'].'_add_more']['#ahah']['path'] of the 'Add another item' submit button in hook_form_alter with the path of a custom #ahah callback. I did this, using the "correct" approach in the #ahah callback and fiddled with $form_state['item_count'][$field_name]. It works for me.
There remains the problem with #required, not yet provided, input elements further down the rendered form as they will get validated for every AHAH submit. I solved the problem by recursively un- and rerequiring the form_elements but it is not pretty and seems like an oversight of the whole AHAH approach in Drupal.
Comment #7
markus_petrux commented@sirkitree: Needs review status means there's a patch for review. I think we cannot change the form_id there because we will be breaking 3rd party code that relies on that.
@sradomski: I see what you mean, but I'm afraid it is now too late in the life cycle of CCK for D6 to change these things. We cannot break existing code. Also please note the AHAH callback attached to "Add more values" button does not validate for form. It's only meant to add a new value to that multiple values field.
I would say here this is "by design", but I leave it as "needs work" in case there's anything that can be added to the hook_form_alter() against 'content_add_more_js' that helps implement this hook. Please, note you can still use FAPI callback for after_built, also pre_render, post_render callbacks. Just think this AHAH process is just meant to change the part of the form related to the "Add more items" button just pressed by the user. The rest of the form should not be altered here because it is not sent back with the AHAH response.
I would even say if you need advanced processing that the AHAH callback provided by CCK does not allow you, then you're free to replace this callback by your own. This approach will not affect the rest of the CCK users, and this is pretty important at this moment in time.
Comment #8
markus_petrux commentedWell, I just added a page to the CCK handbook that describes a method to alter the "Add more items" button text that even works for multigroups.
- Code snippet: How to change the label of the "Add more items" button.
The after_build callback is executed when all elements are already expanded, so the same method could be used to alter almost anything else related to the form elements that exist in the form. Note that this method also works when the AHAH request is processed.
It seems to me there's no need to change the hooks invoked from the AHAH callback attached to the "Add more items" buttons.
Please, feel free to re-open with an example of something that cannot be done using hook_form_alter() + after_build callback.
Comment #9
seanberto commentedSubscribing. Markus, I'm trying to use the approach that you describe in your write-up to edit the "title" label on the AHAH callback but am having a bit of a time finding the name of the form to pass to the _node_form_element_alter_register function. I'll post my solution as soon as I figure it out. Or, if anyone else knows this off the top of their heads, please let me know.
-sean
Comment #10
seanberto commentedAha, I figured it out. I just needed to dive deeper into the form's array. Picking up on Markus's post: