function hook_form_FORM_ID_alter

You are here

7 system.api.php hook_form_FORM_ID_alter(&$form, &$form_state, $form_id)
6 core.php hook_form_FORM_ID_alter(&$form, &$form_state)
8 system.api.php hook_form_FORM_ID_alter(&$form, &$form_state, $form_id)

Provide a form-specific alteration instead of the global hook_form_alter().

Modules can implement hook_form_FORM_ID_alter() to modify a specific form, rather than implementing hook_form_alter() and checking the form ID, or using long switch statements to alter multiple forms.

Note that this hook fires before hook_form_alter(). Therefore all implementations of hook_form_FORM_ID_alter() will run before all implementations of hook_form_alter(), regardless of the module order.


$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.

See also



Related topics


developer/hooks/core.php, line 803
These are the hooks that are invoked by the Drupal core.


function hook_form_FORM_ID_alter(&$form, &$form_state) {
  // Modification for the form with the given form ID goes here. For example, if
  // FORM_ID is "user_register" this code would run only on the user
  // registration form.

  // Add a checkbox to registration form about agreeing to terms of use.
  $form['terms_of_use'] = array(
    '#type' => 'checkbox',
    '#title' => t("I agree with the website's terms and conditions."),
    '#required' => TRUE,


If you use hook_form_FORM_ID_alter() it will run before the implementation
of hook_form_alert() in other modules. This contrains what you can do with hook_form_FORM_ID_alter()

When creating a hook for a CCK field, the format is:


So, for the popular 'foo' module with equally popular 'bar' cck content type:



Sean P. O. MacCath-Moran

Although true for CCK content types, there is no actual CCK field data in the $form variable passed into hook_form_FORM_ID_alter().

To modify CCK fields you have to use hook_form_alter():

see this post:

( sorry for double post i need this posted as a reply to this comment so it gets seen before anyone pulls their hair out trying to figure this out )

The above post is not entirely correct. If you set $form['#after_build'][], you can use hook_form_FORM_ID_alter() to modify CCK fields and not hook_form(), i.e. for the foo module and the bar CCK type:

* Implementation of hook_form_FORM_ID_alter().
function foo_form_bar_node_form_alter(&$form, $form_state) {
$form['#after_build'][] = 'bar_node_form_after_build';


bar_node_form_after_build($form, &$form_state) {
// Alter CCK fields here.

In the above example the code for the 2nd function needs to return $from.

function bar_node_form_after_build($form, &$form_state) {
// Alter CCK fields here.
return $form;

Saved me from a lot of headache!
If you don't return the form, it will give a blank page.

I wanted to add a description for the Title field, I used 'dei' as a name of my module and 'allocator' is the name of my content type (like 'story', 'page', 'webform', etc.).

function dei_form_allocator_node_form_alter(&$form, &$form_state) {
$form['title']['#suffix'] = 'This is the help text for title.';

No need to use #suffix when #description is available.

function dei_form_allocator_node_form_alter(&$form, &$form_state) {
$form['title']['#description'] = 'This is the help text for title.';

Thanks, This code work fine for me

Two examples to illustrate a little bit more how to use hook_form_FORM_ID_alter()

This code set an autocomplete off over the login and the two field of password confirmation (know as "password_confirm")
[concern the create/edit user zone of the back office]

//Add attribute to existing fields without overwritting them
function hook_form_FORM_ID*_alter(&$form, &$form_state) {
$form['account']['name']['#attributes']['autocomplete'] = 'off';
$form['account']['pass']['#after_build'] = array('fct_custom_field_autocomplete_off');


fct_custom_field_autocomplete_off($form_element, &$form_state) {
$form_element['pass1']['#attributes']['autocomplete'] = 'off';

*Note : "FORM_ID" has to be replaced by the name of the form you want to custom, see below.

This code set an autocomplete off over the password field in the authentification page.

//Add attribute to existing field without overwritting it
function hook_form_user_login_alter(&$form, &$form_state) {
$form['pass']['#attributes' ]['autocomplete'] = 'off';

Best regards.

Although true for CCK content types, there is no actual CCK field data in the $form variable passed into hook_form_FORM_ID_alter().

To modify CCK fields you have to use hook_form_alter():

see this post:

So what is the correct form-id to alter the node edit form (for all content types)? I've tried mymodule_form_node_alter(...) and mymodule_form_node_form_alter(...) but neither work. The id of that form is apparently node-form, but '-' is an illegal character in a PHP function name. Do I have to fall back on a generic hook_form_alter and check the id manually?

I want to replace Drupal's preview button with one that saves the node as a draft and then previews in the full site.

Always check for for examples on how to do this: path_form_alter()

You have to use something like this:

function mymodule_form_alter(&$form, $form_state, $form_id) {
  if (isset(
$form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) {
// Do stuff here.

In Drupal 7 we have hook_form_node_form_alter() you can use.

Thanks, I thought this was the case from looking at examples, but wanted to check as it seems rather inefficient to have my function called for every form when it is only applicable to node edits.

Is this not just a bug though?

To save on googling:

Basically, if you want to implement this hook, but you don't know the FORM_ID off the top of your head, open the form in a web browser and view the html code.

find the hidden input field containing the name="form_id" attribute.

So, if you find that the hidden field is:

<input type="hidden" name="form_id" id="edit-og-confirm-subscribe" value="og_confirm_subscribe"  />

Then the name of the function will be: yourmodule_form_og_confirm_subscribe_alter

When using hook_form_FORM_ID_alter(), you will not have access to all the form fields. This might be due to a combine result of using some modules.

For example, $form['attachments'] will not be available in hook_form_FORM_ID_alter() but you will still having in hook_form_alter()


If the form that's being altered is in a block, how do you implement this function? I'm looking to rework a javascript/HTML form, and tweak its authentication, and I'm not sure where to intercept the form data. Many thanks to anyone who can spare the time for an explanation!