Display and Form pseudo fields in Drupal 8 and 9

Pseudo fields are a special type of field that you can add to any content entity type. That means that these fields can be added to nodes, terms, user entity, menu links, blocks, paragraphs, media entity, and any other custom entity type you might have.

The value for a regular field which is added as a base field or via UI is stored in the database, but for a pseudo field, the value is generated in the code. You have full control over the field's value.

Also, you can drag and drop a pseudo field in the "Manage form display" or "Manage display" settings.

Display pseudo fields

Instead of adding some information in a Twig template, you should create a new pseudo field if it is appropriate in your case. Using a pseudo field is a much better solution than just adding stuff to your templates until they are so messy that you have no idea what's going on.

You can change the weight of your pseudo field or hide it completely if you don't need it later on. You can also for example show the pseudo field just on the teaser and hide it for all other displays.

Attaching a pseudo field is super simple. All you have to do is to implement two hooks.

use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_entity_extra_field_info().
 */
function MY_MODULE_entity_extra_field_info() {
  $extra = [];

  $extra['node']['news']['display']['field_thank_you'] = [
    'label' => t('Thank You'),
    'description' => t('Thank You pseudo field.'),
    'weight' => 0,
    'visible' => TRUE,
  ];

  return $extra;
}

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function MY_MODULE_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('field_thank_you')) {
    $thank_you_notice = \Drupal::config('MY_MODULE.settings')->get('thank_you_notice');
    $build['field_thank_you'] = [
      '#type' => 'markup',
      '#markup' => $thank_you_notice,
    ];
  }
}

As you can see we are attaching a new pseudo field called "Thank You" to the News content type (bundle).

Display pseudo field in Drupal 8 and 9
Display pseudo field in Drupal 8 and 9

To add a pseudo field to all content types you can load all Node bundles and do something like this:

use Drupal\node\Entity\NodeType;

foreach (NodeType::loadMultiple() as $bundle) {
  $extra['node'][$bundle->id()]['display']['field_thank_you'] = [
    'label' => t('Thank You'),
    'description' => t('Thank You pseudo field.'),
    'weight' => 0,
    'visible' => TRUE,
  ];
}

If your entity type doesn't have any bundles then use the same value for the first and second index like this:

$extra['task']['task']['display']['field_thank_you'] = [
  'label' => t('Thank You'),
  'description' => t('Thank You pseudo field.'),
  'weight' => 0,
  'visible' => TRUE,
];

The final note for display pseudo fields is to use the proper entity type view hook. So, if you want to add a new pseudo field for example to your Commerce Product entity type, then don't use the MY_MODULE_node_view() but instead, use MY_MODULE_commerce_product_view() hook.

Form pseudo fields

From my personal experience form pseudo fields are less used, but sometimes they do come in handy. To attach a pseudo field to entity form, you also have to implement two hooks.

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_entity_extra_field_info().
 */
function MY_MODULE_entity_extra_field_info() {
  $extra = [];

  $extra['node']['news']['form']['field_thank_you'] = [
    'label' => t('Thank You'),
    'description' => t('Thank You pseudo field.'),
    'weight' => 0,
    'visible' => TRUE,
  ];

  return $extra;
}

/**
 * Implements hook_form_alter().
 */
function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (in_array($form_id, ['node_news_form', 'node_news_edit_form'])) {
    if ($field_intro = $form_state->get('form_display')->getComponent('field_thank_you')) {
      $thank_you_notice = \Drupal::config('MY_MODULE.settings')->get('thank_you_notice');
      $form['field_thank_you'] = [
        '#type' => 'markup',
        '#markup' => $thank_you_notice,
      ];
    }
  }
}

And let's see how this looks like assuming that $thank_you_notice variable has some string value:

Form pseudo field in Drupal 8 and 9
Form pseudo field in Drupal 8 and 9

One drawback of pseudo fields is that you can't display them in a View if you want to show single fields. You have to configure your View to display content and choose an appropriate view mode.

You can overcome this limitation by creating a field plugin for Views. In that case, it makes sense to move the field logic to a service class to avoid writing the same code twice, once in the hook_ENTITY_TYPE_view() hook and once in the field plugin.

You can print a pseudo field in a Twig template just like any other field:

{{ content.field_thank_you }}

And that's pretty much it. Now you know what pseudo fields are and how to add them to entity displays and forms.