Same name and namespace in other branches
- 10 core/lib/Drupal/Core/Form/form.api.php \hook_form_alter()
- 4.7.x developer/hooks/core.php \hook_form_alter()
- 5.x developer/hooks/core.php \hook_form_alter()
- 7.x modules/system/system.api.php \hook_form_alter()
- 8.9.x core/lib/Drupal/Core/Form/form.api.php \hook_form_alter()
- 9 core/lib/Drupal/Core/Form/form.api.php \hook_form_alter()
Perform alterations before a form is rendered.
One popular use of this hook is to add form elements to the node form. When altering a node form, the node object can be retrieved from $form['#node'].
Note that instead of hook_form_alter(), which is called for all forms, you can also use hook_form_FORM_ID_alter() to alter a specific form.
Parameters
$form: Nested array of form elements that comprise the form. The arguments that drupal_get_form() was originally called with are available in the array $form['#parameters'].
$form_state: A keyed array containing the current state of the form.
$form_id: String representing the name of the form itself. Typically this is the name of the function that generated the form.
Related topics
15 functions implement hook_form_alter()
Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.
- book_form_alter in modules/
book/ book.module - Implementation of hook_form_alter(). Adds the book fieldset to the node form.
- color_form_alter in modules/
color/ color.module - Implementation of hook_form_alter().
- comment_form_alter in modules/
comment/ comment.module - Implementation of hook_form_alter().
- default_form_alter in profiles/
default/ default.profile - Implementation of hook_form_alter().
- example_form_alter in developer/
example.profile - Implementation of hook_form_alter().
2 invocations of hook_form_alter()
- drupal_prepare_form in includes/
form.inc - Prepares a structured form array by adding required elements, executing any hook_form_alter functions, and optionally inserting a validation token to prevent tampering.
- upload_js in modules/
upload/ upload.module - Menu-callback for JavaScript-based uploads.
File
- developer/
hooks/ core.php, line 754 - These are the hooks that are invoked by the Drupal core.
Code
function hook_form_alter(&$form, &$form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) {
$path = isset($form['#node']->path) ? $form['#node']->path : NULL;
$form['path'] = array(
'#type' => 'fieldset',
'#title' => t('URL path settings'),
'#collapsible' => TRUE,
'#collapsed' => empty($path),
'#access' => user_access('create url aliases'),
'#weight' => 30,
);
$form['path']['path'] = array(
'#type' => 'textfield',
'#default_value' => $path,
'#maxlength' => 128,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('Optionally specify an alternative URL by which this node can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'),
);
if ($path) {
$form['path']['pid'] = array(
'#type' => 'value',
'#value' => db_result(db_query("SELECT pid FROM {url_alias} WHERE dst = '%s' AND language = '%s'", $path, $form['#node']->language)),
);
}
}
}
Comments
CCK fields missing
Beware that some info like CCK fields are not in $form when you call this, see http://drupal.org/node/726282 for an explanation.
Validating and Saving Submitted data
This hook is useful but documenting how to save/validate these new fields is kinda necessary. Since this document page lacks both of these, here is a quickie example of how to Add a new field, validate it, and then save it. This comment should either be copy/pasted to the d5/d7 doc pages or modified to suit those as well. I dont use either so I cant speak on how things are validated/saved for those versions of hook_form_alter. I assume it's identical.
location of submit and validate properties can vary
it's possible for '#submit' and '#validate' to be an element of the submit button or some other form element instead of a top-level element of the $form array. (for example, rsvp.module's rsvp_reply_form which i'm currently scratching an itch with)
so instead of
$form['#validate'][] = 'nameOfMyModule_functionName_validate'you might need
$form['some_element']['#validate'][] = 'nameOfMyModule_functionName_validate'it's worth finding the #submit and #validate elements in the form you're hooking and following the example
Why is my form not being passed to hook_form_alter
That is the question I asked myself until I discovered the caching settings were essentially bypassing the hook_form_alter process. This is obvious enough, but took me a while to figure this one out. I was attempting to modify a webform block form, and block caching was enabled, hence the form block wasn't being passed through the hook. Makes sense! Hope this helps someone down the road!
Yeah, thats true. In my case,
Yeah, thats true. In my case, clearing caches through UI or drush didn't work. I emptied the tables 'cache_*' from db and got it working. ;)
issue with the hook_form_alter() between contributed modules
The notifications module brought this issue to my attention.
When developers want to modify a form directly, then there is no issue. However, if one module wants to alter the form of another module, it becomes impossible, depending on the order of the modules. For examples, in notifications_ui module:
In order for the subform to be added, this function alters the form. Assuming the modules are executed in alphabetical order, all modules, alphabetically, before notifications (i.e. nodeference module) will not be able to modify any properties of the notifications_ui_form while those afterwards (i.e. views module) will be able to. Can there be a patch in place that will ensure that developers can modify forms that are created from the core and contributed modules that will not cause any conflicts?
FYI, I have not tested the following solution so I will let you know the results when I do.
Using notifications_ui as the basis, my example of a proposed permanent solution is the following:
The caveat is that all developers include a condition that will check for modifications from another module -or- Drupal core can enforce that through the form_alter function. I welcome any feedback to this especially from those who have experienced this issue.
solution does not work as expected
Instead of adding my modifications to the module, it replaces what I added. The original form,
$form[] = notifications_ui_node_subform($node);, does not work either (as stated earlier). If you were to attempt to do something like$form[0]['subscriptions']['#collapsed'] = FALSE;, it will not work. Any suggestions?Reorder module execution with module weight
You can reorder module execution with module weight. One of the ways to change modules weights is to install the Utility module.
This way you get off the
issue.
If you are developing a module you would change your modules weight at install time with something like
Form Alter fields emptied on Preview or failed validation
Any ideas why? When I add fields via form alter or validation fails, my fields added via hook form alter are reset.
This issue may be related: http://drupal.org/node/457630, so I believe this merits some coverage here as well. :)
Node forms
For example, to add custom checkboxes, or other fields to node forms - it is as simple as the following:
(based on the modulename, nodetype and customfield being used)
Careful
This targets both the node edit and the content type edit forms. Use the example in the API!!!!
Add a field to the user contact form. Add the form to a block
What this module does: puts the user contact form (with an added field) into a block so that the author's contact form is displayed on every node that is created by that user.
So first you have to create a your own custom module. This is the code.
Once the module is created, goto administration > blocks then add the block
note 1: to get the form id. first go to the page with the form and view the source code. look for this code and replace the hyphens with underscores.
note 2: more elements for each field here http://api.drupal.org/api/drupal/developer--topics--forms_api_reference....
further clarification
If i understand correctly;
When i put a hook_alter_form in a module, I can use switch() and case to specify the form and actions. I can also use case to specify altering of different forms.
Can i just create a module with the hook and the appropriate $form and have it picked up wherever the form is rendered? Can i have one master module that represents all my alters?, or do i need to add the code in each individual module that i am looking to alter?
Also, can someone point me to some documentation on how to use switch() and case to to filter on $user role?
Thanks much
In Drupal 7, it looks like
In Drupal 7, it looks like form_id is an array and no longer a String.
Way to handle CCK fields in form_alter
If you need to include the cck fields in the form altering process, then use hook_form_alter() instead of hook_form_FORM_ID_alter().
adding submit callback for 'user_profile_form'
For some reason, when I added a submit callback to form 'user_profile_form', I had to also add the default submission handler (function user_profile_form_submit). Otherwise, the form wouldn't be saved. Did not have to do this on *_node_form.
Disable only one radio button in a group of radio buttons
Hi all,
I have a webform under Drupal 6 to subscribe to a schedule for open days.
I wrote a hook_form_alter function which calculates how many places remains for each schedule, and I want to disable the radio button (and only this one) where there is no more places.
How can I do this ?
Thank you by advance
Can't be done with the D6 FAPI...unless you do some core hacking
See the discussion at: http://drupal.org/node/284917
Really?
For D7+ you have this already: http://drupal.org/node/342316#comment-4732130
But for Drupal 6, what is preventing you from adding an #after_build and disabling or restricting access per option? Select lists do not support this (all or nothing), but the others simply require you to set the #access on the radio / checkbox child to false in the after build.