Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
By tim.plunkett on
Change record status:
Published (View all published change records)
Project:
Introduced in branch:
8.0.x
Issue links:
Description:
hook_element_info() allows modules to declare their own Form API/Render API element types and specify their default values.
This is being replaced with an annotated class.
Drupal 7:
function system_element_info() {
$types = array();
$types['textfield'] = array(
'#input' => TRUE,
'#size' => 60,
'#maxlength' => 128,
'#autocomplete_route_name' => FALSE,
'#process' => array(
'form_process_autocomplete',
'ajax_process_form',
'form_process_pattern',
'form_process_group',
),
'#pre_render' => array(
'form_pre_render_textfield',
'form_pre_render_group',
),
'#theme' => 'input__textfield',
'#theme_wrappers' => array('form_element'),
);
// Other types here...
return $types;
Additionally, all of the #process and #pre_render callbacks were separately defined functions
Drupal 8:
/**
* @file
* Contains \Drupal\Core\Render\Element\Textfield.
*/
namespace Drupal\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
/**
* Provides a one-line text field form element.
*
* @FormElement("textfield")
*/
class Textfield extends FormElement {
public function getInfo() {
$class = get_class($this);
return array(
'#input' => TRUE,
'#size' => 60,
'#maxlength' => 128,
'#autocomplete_route_name' => FALSE,
'#process' => array(
array($class, 'processAutocomplete'),
array($class, 'processAjaxForm'),
array($class, 'processPattern'),
array($class, 'processGroup'),
),
'#pre_render' => array(
array($class, 'preRenderTextfield'),
array($class, 'preRenderGroup'),
),
'#theme' => 'input__textfield',
'#theme_wrappers' => array('form_element'),
);
}
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
// ...
}
public static function preRenderTextfield($element) {
// ...
}
}
Element classes must:
- must be in a
Element
subdirectory - must be annotated with either
@RenderElement
or@FormElement
(the value inside the annotation will be the #type name - must implement a
valueCallback
method to replace the form_type_TYPE_value callback - should extend either
\Drupal\Core\Render\Element\FormElement
or\Drupal\Core\Render\Element\RenderElement
Those parent classes define common callbacks that can be reused.
Additionally, you can choose to extend an existing element. For example, class MachineName extends Textfield
to provide the functionality for '#type' => 'machinename'
Impacts:
Module developers