Score:1

Custom theme function for a Field

in flag

I want to change a theme hook for one field from a custom FieldFormatter. It's #theme callback is 'field' but I want to give the user the option to toggle a setting that changes this to 'field_raw', which then uses a Twig template with no markup. I can't figure out the theme hook.

Twig template:

{%- for item in items %}{{ item.content }}{% endfor -%}

Module hook:

function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'field_raw' => [
      'items' => NULL,
    ],
  ];
}

I am unsure of what to pass here that makes it to the twig template. I can output text in the template so I know it is being hit. What is the right variables to set here so the template receives it?

I also tried:

'render element' => 'element'
'render element' => 'elements'
'render element' => 'children'
Score:1
cn flag

Using the field base hook

If this template with no markup should output field values {{ item.content }} you need the core code processing these values by defining a base hook.

See for example comment_theme():

/**
 * Implements hook_theme().
 */
function comment_theme() {
  return [
    ... 
    'field__comment' => [
      'base hook' => 'field',
    ],
  ];
}

In this case it's not enough to start the theme hook name with the base hook, it also needs double underscores: field__raw.


Implementing a custom theme hook

Not recommended, for demonstration purpose, you can copy the relevant core code to your own template:

mymodule.module:

function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'field_raw' => [
      'render element' => 'element',
    ],
  ];
}

function template_preprocess_field_raw(&$variables, $hook) {
  $element = $variables['element'];
  $variables['items'] = [];
  $delta = 0;
  while (!empty($element[$delta])) {
    $variables['items'][$delta]['content'] = $element[$delta];
    $delta++;
  }
}

In this case you can choose a random name for the theme hook, but it must not start with field__.

Switch to this template in the custom field formatter:

  public function view(FieldItemListInterface $items, $langcode = NULL) {
    $elements = parent::view($items, $langcode);
    if (isset($elements['#theme'])) {
      $elements['#theme'] = 'field_raw';
    }
    return $elements;
  }

And finally place the minimal template in the module folder

mymodule/templates/field-raw.html.twig

{%- for item in items %}{{ item.content }}{% endfor -%}
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.