As of Drupal 8.x, four new hooks are available in Field UI API:
- hook_field_formatter_third_party_settings_form()
- hook_field_formatter_settings_summary_alter()
- hook_field_widget_third_party_settings_form()
- hook_field_widget_settings_summary_alter()
The new hooks allow developers to extend field formatters and widgets with third-party settings elements in the Manage Display tabs provided by Field UI. A typical use-case is to extend a field formatter with a new setting, which can be used later when rendering the field, e.g. in hook_preprocess_field().
Comparable hooks were previously provided in Drupal 7.x by the Field Formatter Settings API module in Contrib.
Usage
In this example, we will add a checkbox setting to a field formatter, and retrieve the setting in hook_preprocess_field().
Drupal 7
(requires Field Formatter Settings API module)
/**
* Implements hook_field_formatter_info_alter().
*/
function hook_field_formatter_info_alter(array &$info) {
// Add a setting to a formatter.
$info['foo_formatter']['settings'] += array(
'mymodule_extra_setting' => FALSE,
);
}
/**
* Implements hook_field_formatter_settings_summary_alter().
*/
function hook_field_formatter_settings_summary_alter(&$summary, $context) {
// Append a message to the summary when foo_formatter has
// mymodule_extra_setting set to TRUE for the current view mode.
if ($context['instance']['display'][$context['view_mode']]['type'] == 'foo_formatter') {
$display = $context['instance']['display'][$context['view_mode']];
$settings = $display['settings'];
if (!empty($summary)) {
$summary .= '<br />';
}
if ($settings['mymodule_extra_setting']) {
$summary .= t('My setting enabled.');
}
}
}
/**
* Implements hook_field_formatter_settings_form_alter().
*/
function hook_field_formatter_settings_form_alter(&$settings_form, $context) {
// Add a 'mymodule_extra_setting' checkbox to the settings form
// for 'foo_formatter' formatters.
if ($context['instance']['display'][$context['view_mode']]['type'] == 'foo_formatter') {
$display = $context['instance']['display'][$context['view_mode']];
$settings = $display['settings'];
$settings_form['mymodule_extra_setting'] = array(
'#type' => 'checkbox',
'#title' => t('My setting'),
'#default_value' => $settings['mymodule_extra_setting'],
);
}
}
/**
* Implements hook_preprocess_field().
*/
function hook_preprocess_field(&$variables) {
// Provide an extra variable to the field template when the field uses
// a formatter of type 'foo_formatter'
if ($variables['element']['#formatter'] == 'foo_formatter') {
$entity_type = $variables['element']['#entity_type'];
$field_name = $variables['element']['#field_name'];
$bundle = $variables['element']['#bundle'];
$view_mode = $variables['element']['#view_mode'];
$formatter_settings = field_formatter_settings_get_instance_display_settings($entity_type, $field_name, $bundle, $view_mode);
// make the setting available in the field template
$variables['mymodule_extra_setting'] = $formatter_settings['mymodule_extra_setting'];
}
}
Drupal 8
/**
* Implements hook_field_formatter_settings_summary_alter().
*/
function hook_field_formatter_settings_summary_alter(&$summary, $context) {
// Append a message to the summary when foo_formatter has
// my_setting set to TRUE for the current view mode.
if ($context['formatter']->getPluginId() == 'foo_formatter') {
if ($context['formatter']->getThirdPartySetting('my_module', 'my_setting')) {
$summary[] = t('My setting enabled.');
}
}
}
/**
* Implements hook_field_formatter_third_party_settings_form().
*/
function hook_field_formatter_third_party_settings_form($plugin, $field_definition, $view_mode, $form, $form_state) {
$element = array();
// Add a 'my_setting' checkbox to the settings form for 'foo_formatter' field
// formatters.
if ($plugin->getPluginId() == 'foo_formatter') {
$element['my_setting'] = array(
'#type' => 'checkbox',
'#title' => t('My setting'),
'#default_value' => $plugin->getThirdPartySetting('my_module', 'my_setting'),
);
}
return $element;
}
/**
* Implements hook_preprocess_field().
*/
function hook_preprocess_field(&$variables) {
// Provide an extra variable to the field template when the field uses
// a formatter of type 'foo_formatter'
if ($variables['element']['#formatter'] == 'foo_formatter') {
$entity = $variables['element']['#object'];
$view_mode = $variables['element']['#view_mode'];
$field_name = $variables['element']['#field_name'];
// get the field formatter settings...
$entity_display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
$field_display = $entity_display->getComponent($field_name);
// make the setting available in the field template
$variables['my_module_my_setting'] = $field_display['third_party_settings']['my_module']['my_setting'];
}
}
Notes
- In Drupal 7.x, the formatter
$summary
variable was passed intohook_field_formatter_settings_summary_alter()
as a string. It was typically necessary to add a <br> to keep the summary display tidy.In Drupal 8.x, the
$summary
variable is an array (passed by reference) so there is no need to add the <br> manually. - The contrib hook
hook_field_formatter_settings_form_alter()
is replaced byhook_field_formatter_third_party_settings_form()
in Drupal 8.x. - In Drupal 7.x, field_formatter_settings.module provided a helper function to retrieve the field formatter display settings: field_formatter_settings_get_instance_display_settings().
In Drupal 8.x, the field formatter settings can be retrieved using EntityViewDisplay::collectRenderDisplay() and EntityDisplayBase::getComponent().
Comments
hook_field_attach_view_alter() deprecated, how to solve?
I'm porting the Field HTML Trim module to 8.x-1.x. I used to be able to use hook_field_attach_view_alter() to alter the field output but it's now deprecated. This example proposes the use of hook_preprocess_field(). But I only need to extend the text formatters from core. So I needed to unset the #pre_render property of the item's content in order for the hook_preprocess_field() to not be overridden by it.
So my question is: is there a way to actually extend core's field formatter plugins? Instead of unsetting it's behavior which seems unnatural...
Add the import statements to the Drupal 8 example
To get the above code for Drupal 8 to work out of the box,
The following import statements will have to be added just below the <?p h p line
Please change the document to reflect that,
Thanks