On this page
- Form Elements
- List of form and render elements
- Properties
- HTML5 Form Render Elements
- Other useful render elements
- Altering or adding form elements
- Finding the form identifier
- Decide between hook_form_alter and hook_form_FORM_ID_alter
- Finally some examples
- Alter existing form fields example
- Add a new form field example
Form Render Elements
Form Elements
Form render elements are a subset of render elements, representing elements for HTML forms, which can be referenced in form arrays.
List of form and render elements
The class Drupal\Core\Render\Element\FormElementBase provides a base class for form element plugins
Before 10.3 Drupal\Core\Render\Element\FormElement was used but it is deprecated and will be removed in Drupal 12.
There is no list of all available form and render elements. To learn which form and render elements are available check classes that implement Drupal\Core\Render\Element\FormElementInterface and Drupal\Core\Render\Element\ElementInterface respectively.
Keep in mind that form elements and render elements are similar (both represents a component that is rendered to HTML when serving the response) but they are not exactly the same. Form elements are intended to be use in the context of a Form build method and render elements are used in render arrays. Because Form objects returned by form build methods are converted to render arrays you can also use render elements in the context of a Form build method.
Properties
Here is a list of properties that are used during the rendering and form processing of form elements:
- #access: (bool) Whether the element is accessible or not; when FALSE, the element is not rendered and the user submitted value is not taken into consideration.
- #after_build: (array) Array of callables or function names, which are called after the element is built. Arguments: $element, $form_state.
- #ajax: (array) Array of elements to specify Ajax behavior. See the Javascript API and AJAX Forms guides for more information.
- #array_parents: (string[], read-only) Array of names of all the element's parents (including itself) in the render array. See also #parents, #tree.
- #default_value: Default value for the element. See also #value.
- #description: (string) Help or description text for the element. In an ideal user interface, the #title should be enough to describe the element, so most elements should not have a description; if you do need one, make sure it is translated. If it is not already wrapped in a safe markup object, it will be filtered for XSS safety.
- #description_display: (string) Where and how to display the #description. Possible values:
- after: Description goes after the element (default).
- before: Description goes before the element.
- invisible: Description is there but is made invisible using CSS.
- #disabled: (bool) If TRUE, the element is shown but does not accept user input.
- #element_validate: (array) Array of callables or function names, which are called to validate the input. Arguments: $element, $form_state, $form.
- #prefix: (string) Prefix to display before the HTML input element. Should be translated, normally. If it is not already wrapped in a safe markup object, will be filtered for XSS safety.
- #suffix: (string) Suffix to display after the HTML input element. Should be translated, normally. If it is not already wrapped in a safe markup object, will be filtered for XSS safety.
- #input: (bool, internal) Whether or not the element accepts input.
- #parents: (string[], read-only) Array of names of the element's parents for purposes of getting values out of $form_state. See also #array_parents, #tree.
- #process: (array) Array of callables or function names, which are called during form building. Arguments: $element, $form_state, $form.
- #processed: (bool, internal) Set to TRUE when the element is processed.
- #required: (bool) Whether or not input is required on the element.
- #required_error: (string) Override default error message "@field_title is required" will be used if this is undefined.
- #states: (array) Information about JavaScript states, such as when to hide or show the element based on input on other elements. Refer to FormHelper::processStates.
- #title: (string) Title of the form element. Should be translated.
- #title_display: (string) Where and how to display the #title. Possible values:
- before: Label goes before the element (default for most elements).
- after: Label goes after the element (default for radio elements).
- invisible: Label is there but is made invisible using CSS.
- attribute: Make it the title attribute (hover tooltip).
- #tree: (bool) TRUE if the values of this element and its children should be hierarchical in $form_state; FALSE if the values should be flat. See also #parents, #array_parents.
- #value: Used to set values that cannot be edited by the user. Should NOT be confused with #default_value, which is for form inputs where users can override the default value. Used by: button, hidden, image_button, submit, token, value.
- #value_callback: (callable) Callable or function name, which is called to transform the raw user input to the element's value. Arguments: $element, $input, $form_state.
HTML5 Form Render Elements
The HTML5 elements are:
'#type' => 'tel'
(See Tel)'#type' => 'email'
(See Email)'#type' => 'number'
(See Number)'#type' => 'date'
'#type' => 'url'
'#type' => 'search'
'#type' => 'range'
Using these elements as opposed to requesting data in plain textfields is preferable because devices can pull up the proper input methods for them, such as when a telephone number is requested, a keypad screen would display on a device.
Other useful render elements
- details: The
'#type' => 'details'
element is a grouping element with a summary. - vertical_tabs: The
'#type' => 'vertical_tabs'
element allows grouping of fields in vertical tabs. - language_select: The
'#type' => 'language_select'
element is a language selector to make it easy to put language configuration on forms. - dropbutton: The
'#type' => 'dropbutton'
provides a generic select list with a dropbutton. See also the'#type' => 'operations'
element. - operations: The
'#type' => 'operations'
element provides a list of available operations, which you can commonly find in entity configuration administrative screens, such as at admin/structure/types. - entity_autocomplete: The
'#type' => 'entity_autocomplete'
element allow to select an entity of a specific type.
Check out namespace Drupal\Core\Render\Element for all the core provided elements.
You can also get a relevance list on the the Elements API page.
Altering or adding form elements
This chapter talks about adding new fields or altering existing fields on forms that are already available on your Drupal site. If you want to create new forms, you may follow the guide at Introduction to Form API beforehand, which provides a basic form creation example that gets you started.
No matter if you want to change existing fields or add new fields to an existing form, you'll have to implement hook_form_alter
or hook_form_FORM_ID_alter
.
Finding the form identifier
Because you only want to alter (a) specific form(s), you'll first have to find out which identifier (ID) the form(s) use(s).
hook_form_alter
provides the $form_id
as a parameter.
- Create or reuse an existing custom module. For the purpose of this guide, the module's machine name is
mymodule
. - In the mymodule.module file, implement the
hook_form_alter
like the following and use your preferred variable dumper:
/** * Implements hook_form_alter(). */ function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { /** * Use your debugging tool to print the $form_id value. * Examples below: */ // Symfony dump: dump($form_id); // kint: kint($form_id); }
- Load the page which contains the form.
- The ID should display somewhere in the page. Depending on your active theme, you may need to look in the DOM inspector or page source if it does not show up.
If configured on your work environment, you may also use a PHP debugger like XDebug to get the $form_id
value instead of printing it. Multiple hook calls will eventually occur, one for each form on the loaded page (there may be a lot of those calls: user login, search bar, autocompletes, etc!). You just have to remember the $form_id
of the desired form(s) to alter.
Decide between hook_form_alter
and hook_form_FORM_ID_alter
You have your $form_id
? Good! Now, that's when you'll have to decide between hook_form_alter
and hook_form_FORM_ID_alter
.
If you want to alter various forms at the same time, like adding/altering common fields to all of them, you'll want to use hook_form_alter
. It is called for every forms loaded in your page. You'll need to use multiple if
or a switch
to handle all the form identifiers; the choice is yours.
If you want to alter a single form, you'll want to use hook_form_FORM_ID_alter
. It is only called for the form when FORM_ID
matches $form_id
. For instance, mymodule_form_user_login_alter
will only be called when the user_login
form is rendered.
Finally some examples
Alter existing form fields example
/**
* Implements hook_form_alter.
*
* Alters the display of a form
*/
function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
//get the id of the form you want to alter
//kint($form_id);
//let's alter the edit form of your custom content type
if($form_id == 'node_yourcontenttype_edit_form') {
//get a look at the form array, which amongst other stuff
//shows the available fields
//kint($form);
//hide revision settings form
$form['revision_information']['#access'] = false;
//set some number field to readonly.
$form['field_summe']['widget'][0]['value']['#attributes']['readonly'] = true;
//change description of a telephone number field
$form['phone_number']['#description'] = t('Start with + and your country code.');
//attach our custom js library to the forms.
//you'll have to define this library in your module's mymodule.libraries.yml
$form['#attached']['library'][] = 'mymodule/mylibrary';
}
}
Add a new form field example
/**
* Implements hook_form_alter.
*
* Alters the display of a form
*/
function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
//get the id of the form you want to alter.
//kint($form_id);
//let's alter the edit form of your custom content type
if($form_id == 'node_yourcontenttype_edit_form') {
//Get a look at the form array, which amongst other stuff shows the available fields
//kint($form);
//Add some custom markup to your form.
//We can basically add any field here. But if we want to save it's value
//we'll have to make sure to do something with the entered value in our form submit handler.
$markup = '<div id="my-custom-markup"><h1>Here is my markup</h1></div>';
$form['field_mycustommarkup'] = [
'#type' => 'markup',
'#markup' => $markup,
//use #weight to move this field up and down on your form.
//check other forms' weights to find out, what weight to use.
'#weight' => 1,
];
//Let's say this form has some field groups, or group tabs.
//We want to place the custom markup inside this group.
//Get a list of all groups on this form and their children.
//kint($form['#group_children'])
//Let's say our group is called group_someoptions and we wnat to place the custom markup
//inside this group.
$form['#group_children']['field_mycustommarkup'] = 'group_someoptions';
}
}
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion