I have two templates: - a child that is printing each item in a list; - and a parent that calls it there is also an intermediate Field template that is not involved.

The parent has preprocess access to node field data that each child (node teaser) call needs to use. The child is printing items in a multivalue entity reference field.

How can the child get the data from the parent felds so it can print the right html?

Edit: Just in case it's not clear, the situation is:

paragraph_entity        <== preprocess hook can see field_settingsN which change how "B" and "A" render (e.g. add/change attrs, class).
  -> field_settings_1
  -> field_settings_2
  -> field_references   <== have a defined template "B"
    -> 1.. entity refs to nodes
      -> node           <== have a defined (teaser) template "A"
  • I was hoping the parent can save some data in the environment of the child... is that possible?
    – rivimey
    Commented May 12, 2019 at 13:18
  • 1
    100% doable. Actually did this within the last week, answer coming right up. Commented May 12, 2019 at 13:45

1 Answer 1


Done this a couple times, but really got the caching better last time so that it works perfectly... I've put in some fairly verbose comments, but if anything is unclear just shout.

 * Implements HOOK_preprocess_paragraph().
function HOOK_preprocess_paragraph(array &$vars) {
  /** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
  $paragraph = $vars['paragraph'];
  // Change 'content_reference' to be your paragraph bundle's machine name.
  if ($paragraph->bundle() === 'content_reference') {
    // Instead of 10 set that to be the max number of references in the field.
    foreach (range(0, 10) as $i) {
      // Change all references to 'field_content_reference' to use your field's
      // machine name.
      if (!isset($vars["content"]["field_content_reference"][$i])) {
      /** @var \Drupal\node\Entity\Node $node */
      $node = $vars["content"]["field_content_reference"][$i]["#node"];

      // Example change to the Node.
      $node->field_parent_paragraph = $paragraph;
      $changed = TRUE;

      if (isset($changed)) {
        // If we've changed the node, give a new cache id.
        $vars["content"]["field_content_reference"][$i]['#cache']['tags'][] = "paragraph:{$paragraph->id()}";
        $vars["content"]["field_content_reference"][$i]['#cache']['keys'][] = "paragraph";
        $vars["content"]["field_content_reference"][$i]['#cache']['keys'][] = $paragraph->id();

Follow that up with something like:

 * Implements HOOK_preprocess_node().
function HOOK_preprocess_node(array &$vars) {
  /** @var \Drupal\node\Entity\Node $node */
  $node = $vars['node'];
  if (isset($node->field_parent_paragraph)) {
    $paragraph = $node->field_parent_paragraph;
    $vars['content']['#attributes']['class'][] = $paragraph->field_settings_1->value;
  • Thanks, Nick. If I understand, you're setting a value on just the in-memory copy of referenced nodes, so when they are rendered they can look up their parent and determine the needed settings?
    – rivimey
    Commented May 12, 2019 at 14:07
  • I don't want to risk saving such local changes, because a given referenced node may well be referenced from more than one place.
    – rivimey
    Commented May 12, 2019 at 14:08
  • Pretty much. In that example I didn't actually set any parent reference - instead I set the title on the node to match an imaginary title field on the paragraph. I'll do a slight change actually to match your example need a bit better. Commented May 12, 2019 at 14:09
  • As long as you don't call $node->save() it won't save the changes anywhere. Commented May 12, 2019 at 14:10
  • 1
    That's great..For the sake of other readers, I presume in the second part the field_paragraph should be field_parent_paragraph?
    – rivimey
    Commented May 12, 2019 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.