One of the challenges front-end developers face is adding new components to entity templates that exist outside of what is defined in the Field API; or in other words, adding dynamic components that aren’t really fields. Often this can be easily done by throwing the custom markup in a .html.twig
file and calling it a day. But if you’re working on something that needs to be reusable, or if you’re collaborating with a site builder who doesn’t write code, the custom template route can be limiting.
Enter hook_entity_extra_field_info()
.
Content Moderation: A “Pseudo-Field” in Core
Drupal’s documentation says this hook “exposes ‘pseudo-field’ components on content entities.” You can see this hook in action with the Content Moderation module in core. All moderation-enabled entities can have an option box, placed via that entity’s Manage Display page, that contains a widget to update an entity’s moderation state in place rather than clicking through to the edit page.
The moderation option isn’t a real field. Rather, it’s what Drupal calls a “Pseudo Field.” But by using hook_entity_extra_field_info()
, you wouldn’t know the difference. The moderation option can be moved around and configured for various display modes, just like “real” fields.
Using hook_entity_extra_field_info in a Custom Module
On a recent project, we needed to integrate a newer commenting service called Coral Talk. After searching, we learned that no module existed to integrate this service in Drupal. This presented a perfect use case for an Extra Field, and only needed two hooks for the bulk of the work:
/** * Implements hook_entity_extra_field_info(). */ function coral_talk_entity_extra_field_info() { // Load commenting configuration. $config = \Drupal::config(coral_talk.settings'); $extra = []; // Loop over the content types configured to have comments // and get their bundle name. foreach ($config->get('content_types') as $bundle) { if ($bundle) { // Add info for Extra Field to nodes only, specific to configured // content types. This determines what shows on Manage Display. $extra['node'][$bundle]['display'][‘coral_talk_comments'] = [ 'label' => t(‘Coral Talk Comments'), 'description' => t('Place commenting on the page.'), 'weight' => 100, 'visible' => TRUE, ]; } } // Return our new extra field. return $extra; }
After a cache clear, this new field will appear on the configured content types’ Manage Display page and can be placed on the content type along with the other fields for that content type. Now that the field is defined, it needs some info for what should be rendered to the page. This is handled by Drupal’s hook_ENTITY_TYPE_view()
hook.
/** * Implements hook_ENTITY_TYPE_view(). */ function coral_talk_node_view( array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode ) { // 1. Check to see if our new field should be rendered on the entity display. // 2. Determine whether the user has permission to add comments. $condition = ( $display->getComponent(‘coral_talk_comments') && \Drupal::currentUser()->hasPermission('create coral comment') ); if ($condition) { $config = \Drupal::config(coral_talk.settings'); // Add the new field to the $build array with a call to a custom theme // hook to render the comments. Pass necessary config into comment // settings. $build[‘coral_talk_comments'] = [ '#theme' => 'coral_talk_comments', '#domain' => $config->get('domain') ?? '', ]; } }
After another cache clear, we’ll now see our comments being rendered to our content types in whichever view mode they’re enabled on. The moves setup of comments outside of code and into a place that’s more accessible and flexible for various users.
This approach is great for simple scenarios. One drawback, however, is that it’s not possible to define any custom configuration options for these pseudo fields. Each extra field is identical, and any configuration has to be hard coded in these hooks. This presents challenges for site builders, who might want to configure comments differently per content type however. Fortunately, there is a solution in contrib that changes how Extra Fields are defined and allows for developers to add configuration to each field. In the next post, we’ll explore the Extra Field Settings Provider module.