How to change an existing Drupal form
Drupal 7 Case
Changing an existing form is one of the first things that new Drupal developers will learn how to do. It is a natural extension from site building, where you might need to change one thing on a form created by a core or contributed module. One of the benefits of using the Form API to construct forms is that any module can alter any other modules form. In this tutorial, you are going to learn how to alter a Drupal form.
Add a message to Create Article form
Go to Add Content -> Article. This is the form that you are going to alter.
To alter a form, you need to call hook_form_alter(). Add an empty implementation of hook_form_alter(), like so:
/**
* Implements hook_form_alter().
*/
function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
}
To alter a form, you need to know its ID. There are two easy ways to find a form’s ID.
1. View source
The form ID will be the HTML ID in the form element. Here you can see that the form ID is article-node-form.
2. Print all Form IDs in form alter
Inside the hook_form_alter(), print a message to display the form_id.
function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
dpm($form_id);
}
You will need to clear cache to see the dpm().
$ drush cc all
So the form ID is article_node_form. If you are really observant, you will have noticed that when viewing the source code, the form ID has hyphens instead of underscores. It should always be with underscores, so if you use the view source method, you will need to convert the hyphens to underscores.
We are going to change all the code inside the form alter function.
function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'article_node_form') {
$form['field_message'] = array(
'#type' => 'item',
'#title' => t('New article'),
'#markup' => t('You are about to create a new article'),
);
}
}
First, you added a condition to check that the form ID is article_node_form. Then you added a new form element, called field_message. This contains a message and is not a normal field like a textfield. You use the type item for this.
From api.drupal.org:
Item Generate a display-only form element allowing for an optional title and description.
If you reload the form, you should see the message. However, it is displayed below the tag, title, body and image fields. Not exactly what we want. To fix this, you need to add a weight to the field and weight it above the other fields.
You need to find out the weight of the existing fields. Let’s add the dpm($form) back into and inspect the relevant fields.
function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'article_node_form') {
$form['field_message'] = array(
'#type' => 'item',
'#title' => t('New article'),
'#markup' => t('You are about to create a new article'),
);
dpm($form);
}
}
Expand the title field, as that is the first field on the rendered form.
If you add a weight that is higher than −5, the new field will be positioned above the title field.
function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'article_node_form') {
$form['field_message'] = array(
'#type' => 'item',
'#title' => t('New article'),
'#markup' => t('You are about to create a new article'),
'#weight' => -6,
);
}
}
Drupal 9 Case
All hooks should be in file module_name.module
add API declaration:
use Drupal\Core\Form\FormStateInterface;
at the top of the file.
now review this example:
/**
* Implements hook_form_FORM_ID_alter().
*/
function complex_form_node_complex_document_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
$complex_id = VisitController::getLastVisitComplex();
if ($complex_id > 0) {
$form['field_document_complex']['#access'] = FALSE;
$form['field_document_complex']['widget']['#default_value']['target_id'] = $complex_id;
}
}
form id is: node_complex_document_form
This alter is activated just before the form is built and sent to the client.
some of the form element has widget, like entity_reference fields, in the case of entity_reference the #default_value represents an entity.