It would be great if pseudo fields added via hook_field_extra_fields() could have their label actually displayed within the context of the node (or entity) being viewed in the same way "normal" fields have their label displayed. Currently, the simplest way that I have found to display an inline label for an extra field that fits in with the rest of my fields is to do something like:

<?php
$node->content['mymodule_pseudo_field'] = array(
  '#prefix' => '<div class="field field-label-inline clearfix"><div class="field-label">My Pseudo Field</div>',
  '#suffix' => '</div>',
  '#markup' => '<div class="field-items">' . $my_pseudo_value . '</div>',
);
?>

This is a pretty messy way of doing it.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mkadin’s picture

+1 for this feature. It would be useful for EVA: Entity Views Attachment to implement.

charlie-s’s picture

I ended up implementing a custom theme wrapper that does this in 1 place and is reused as I add custom fields to a particular node view. Here's an example:

<?php

/**
 * Implements hook_theme.
 */
function mymodule_theme() {
  return array(
    'pseudo_field' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Theme output of a pseudo_field.
 */
function theme_pseudo_field($variables) {
  if (isset($variables['element']['#label_display']) && $variables['element']['#label_display'] == 'inline') {
    $output = "
      <div class='field field-label-inline clearfix'>
        <div class='field-label'>{$variables['element']['#label']}</div>
        <div class='field-items'>{$variables['element']['#field']}</div>
      </div>";
  } else {
    $output = "
      <div class='field'>
        <div class='field-label'>{$variables['element']['#label']}</div>
        <div class='field-items'>{$variables['element']['#field']}</div>
      </div>";
  }
  return $output;
}

/**
 * Implements hook_node_view().
 */
function mymodule_node_view($node, $view_mode, $langcode) {
  if ($node->type == 'foo') {
    $node->content['some_custom_field'] = array(
      '#theme_wrappers' => array('pseudo_field'),
      '#label' => 'Some Custom Label',
      '#label_display' => 'inline',
      '#field' => 'some custom data',
    );
    $node->content['another_custom_field'] = array(
      '#theme_wrappers' => array('pseudo_field'),
      '#label' => 'Another Custom Label',
      '#label_display' => 'inline',
      '#field' => 'another bit of custom data',
    );

    // Since #label_display is not set to inline, this label will display above the field value.
    $node->content['label_above'] = array(
      '#theme_wrappers' => array('pseudo_field'),
      '#label' => 'Above Label',
      '#field' => 'some data',
    );
  }
}
?>

This could be done in many places, but I think you get the idea. Still might be nice to have an extra field be displayed more like a traditional field without the need for the "mimic" code above.

Boobaa’s picture

+1 for this feature; additionally, it would be great if one could select different formatters for extra fields as well.

Pol’s picture

I'm also looking for this.

We have to look into \Drupal\field_ui\DisplayOverview::buildExtraFieldRow

I've replaced:

    // Insert an empty placeholder for the label column.
    $label = array(
      'empty_cell' => array(
        '#markup' => '&nbsp;'
      )
    );

with

    $display_options = $entity_display->getComponent($field_id);

    // Insert the label column.
    $label = array(
      'label' => array(
        '#type' => 'select',
        '#title' => $this->t('Label display for @title', array('@title' => $extra_field['label'])),
        '#title_display' => 'invisible',
        '#options' => $this->getFieldLabelOptions(),
        '#default_value' => $display_options ? $display_options['label'] : 'above',
      ),
    );

But I'm not able to 'save' the configuration of it.

I've looked in the Overview Form here: \Drupal\field_ui\DisplayOverviewBase::submitForm

Modifying the loop for extra fields like this:

    // Collect data for 'extra' fields.
    foreach ($form['#extra'] as $name) {
      if ($form_values['fields'][$name]['type'] == 'hidden') {
        $display->removeComponent($name);
      }
      else {
        $display->setComponent($name, array(
          'weight' => $form_values['fields'][$name]['weight'],
          'label' => $form_values['fields'][$name]['label'],
        ));
      }
    }

Allows me to save the 'label' property correctly.

We could also save the whole array, like that:

    // Collect data for 'extra' fields.
    foreach ($form['#extra'] as $name) {
      if ($form_values['fields'][$name]['type'] == 'hidden') {
        $display->removeComponent($name);
      }
      else {
        $display->setComponent($name, $form_values['fields'][$name]);
      }
    }

What do you think ?

Also, don't forget to change: \Drupal\entity\EntityDisplayBase::getComponent:

  public function getComponent($name) {
    // We always store 'extra fields', whether they are visible or hidden.
    $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext);
    if (isset($extra_fields[$name])) {
      // If we have explicit settings, return an array or NULL depending on
      // visibility.
      if (isset($this->content[$name])) {
        if ($this->content[$name]['visible']) {
          return $this->content[$name];
        }
        else {
          return NULL;
        }
      }

      // If no explicit settings for the extra field, look at the default
      // visibility in its definition.
      $definition = $extra_fields[$name];
      if (!isset($definition['visible']) || $definition['visible'] == TRUE) {
        return $definition;
      }
      else {
        return NULL;
      }
    }

    if (isset($this->content[$name])) {
      return $this->content[$name];
    }
  }

Instead of returning the array containing the weight, I return the whole element/definition.

Now, to render that extra field correctly, it's here \Drupal\node\NodeRenderController::buildContent:

      // Add Language field text element to node render array.
      if ($display->getComponent('language')) {
        $entity->content['language'] = array(
          '#type' => 'item',
          '#title' => t('Language'),
          '#markup' => language_name($langcode),
          '#prefix' => '<div id="field-language-display">',
          '#suffix' => '</div>'
        );
      }

$display->getComponent('language') returns an array with the 'label' and the 'weight' as key and their respective values, so it's cool, we can retrieve the values we saved in the manage form display screen.

Now, we need to find a way to use the field template, I'm still digging...

BTW, what happend when I render multiple node on a page, does the language field has always the same ID ?

Pol’s picture

Attaching a patch, it's easier to see the changes.

swentel’s picture

I guess the best place is probably going to be EntityFormController::processForm()

- edit - at least for the forms side - should check where we assign/change the weights on the display side

- edit - I just realized that on the forms side there's no label, so that doesn't matter at all, scrap my comment ...

maijs’s picture

Issue summary: View changes

If you're interested in easily making extra fields look like real fields, check out Pseudo field contrib module.

kenorb’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 5: drupal8.field-system.1471706-5.patch, failed testing.

johnv’s picture

I tried to investigate how the title of extra_field is displayed on a view mode, using the Bartik theme on D8-rc2. I did not succeed :-(
I compared my own field from Field UI with the core 'Language' property (which is the only one exposed for view_modes).

In the display settings fo the Node type, you can set the label placing.

When viewing a node, Core/Field/FormatterBase.php::view() collects all info for each field. Both field and property are the same:

view Drupal\Core\Field\Plugin\Field
'#theme' => string(5) "field"
'#title' => object Drupal\Core\StringTranslation\TranslatableMarkup(5) 
'#label_display' => string(6) "inline"  // <== This is the settings we are looking for.
'#field_name' => string(8) "langcode" // <== vs. MY_FIELD_NAME
'#field_type' => string(8) "language" // <== vs. 'list_default'

So the hook_field_extra_fields (title display and weight) are recollected correctly.
(Apparently, '#title_display' is for forms, '#label_display' is for view_modes.)

Core/Entity/EntityViewBuilder::buildMultiple() collects all info from hooks.
There, the '#label_display' has vanished for Language! (Why, where?) I added a hardcoded
$build_list[$key]['langcode']['#label_display'] = "inline";

I investigated the differences between the both formatters:
- Drupal\options\Plugin\Field\FieldFormatter\OptionsDefaultFormatter
- Drupal\Core\Field\Plugin\Field\FieldFormatter\LanguageFormatter
There are no diffences in handling the title/label.

This is all passed through Drupal\Core\Render\Renderer->doRender(), also with no apparent differences.
In modules/system/templates/field.html.twig, a variable 'label_display' is passed, but not used.

So, two questions remain:
- Why/where is the settings '#label_display' removed?
- When restored, why/where is it not used? Somewhere, there is a difference between fields and basefields/properties.

johnv’s picture

@Pol, the first part of your search is already fulfilled: Core stores the title settings corectly in the Entity Configuration.

BTW. I'm interested in this issue for diaplsy properties of custom entities, not the language property per se.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ao2’s picture

Hi, I rebased the patch to 8.3.x just to see the effect, It looks like it allows to set the label behavior, but obviously this is not enough or render the label.

@Pol did you look into the rendering part?

I am going to look at the "Pseudo field" plugin next, but I was also wondering if in the long run having pseudo fields as a new FieldType and adding them using the Plugin API would make sense. Not an experiment I can do myself I am afraid.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

iyyappan.govind’s picture

Hi All, I like this feature. I have initiated the testing with Drupal 8.9. Also this will fix the other issue - Implement visibility options for "Real name" field label.

Thanks

apaderno’s picture

Version: 8.6.x-dev » 8.9.x-dev

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

vensires’s picture

I don't know if we really need something more than the following:

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function MYMODULE_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('MYFIELD')) {
    $node->content['MYFIELD'] = array(
      '#theme' => 'field',
      '#label_display' => 'inline',
      '#view_mode' => '_custom',
      '#title' => t('MY LABEL'),
      '#field_type' => 'text',
      '#field_name' => 'MYFIELD',
      '#bundle' => $entity->bundle(),
      '#entity_type' => $entity->getEntityTypeId(),
      '#object' => $entity,
      '#is_multiple' => FALSE,
      '#items' => array(array()),
      0 => array(
        '#markup' => 'YOUR CONTENT HERE',
      ),
    );
  }
}

I also have it as a snippet for D7 and for D8+ in https://gitlab.com/-/snippets/1749165.

junaidpv’s picture

This issue can be solved by using extra_field_plus module. See the example module within it.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.