1

I'm using entity print and I would like to get node variables in my twig template, so I can call them like {{ content.field_name }}.

I tried using a preprocess function but I'm not sure I'm doing things well.

Assuming I have a twig template called entity-print.html.twig, here the preprocess functions I tried :

function THEMENAME_template_preprocess_entity_print(&$vars) {
    $vars['field_name'] = $entity->get('field_name')->getValue();
  }

I also tried

  function THEMENAME_template_preprocess_entity_print(&$vars) {
    $vars['field_name'] = $entity->get('field_name')->value;
  }

I'm calling field_name with all of this twig variable for debugging purpose :

   1 {{ content.field_name.0 }}
   2 {{ content.field_name.value }}
   3 {{ content.field_name.0.value }}
   4 {{ field_name.content }}
   5 {{ content.field_name[0] }}
   6 {{ node.field_name.value }}

Nothing come. What am I doing wrong ? Do I have to make a custom module ?

7
  • Your problem here is that $entity is not defined.
    – No Sssweat
    Aug 29, 2017 at 17:48
  • try adding $entity = \Drupal::routeMatch()->getParameter('node');
    – No Sssweat
    Aug 29, 2017 at 20:05
  • Hi @NoSssweat, thanks for helping. So using $entity = \Drupal::routeMatch()->getParameter('node'); $vars['field_make'] = $entity->get('field_make')->getvalue(); I get page error with "website is currently unable to handle this request."
    – Aporie
    Aug 30, 2017 at 8:40
  • Hmm ok, let me ask you this, Why aren't you using node--[type].html.twig or node--[nodeid].html.twig? Why did you create entity-print.html.twig ?
    – No Sssweat
    Aug 30, 2017 at 8:55
  • Because I just want to theme the pdf and not the entire node layout.
    – Aporie
    Aug 30, 2017 at 8:57

3 Answers 3

3

Looks like you need to review Entity Print in Drupal 8 again. I am using the Entity Print module and it works just fine. Here are some pointers I would recommend below. Your original post is regarding printing node variables in twig templates

  1. On your content type, navigate to Manage Display-->Expand Custom Display Settings-->Enable PDF. This will create a PDF view mode (which is used for printing)
  2. Create a twig template node--article--pdf.html.twig (replace article with machine name of your content type)
  3. Update your_theme.info.yml and your_theme.libraries.yml as suggested in Entity Print in Drupal 8 so you can control the theme and assign a css file only for print
  4. Copy and add entity-print.html.twig to your subtheme
  5. Using node--article--pdf.html.twig, you can control whatever variable you need. However, I recommend you use the PDF view mode first to see what it can do for you.

I have yet to use a preprocess function and you should only need that if you need additional processing. Using the PDF view mode, entity-print.html.twig and the node--article--pdf.html.twig templates you will be able to print as you need.

Ultimately, you should use the PDF view mode so you can manage the PDF view mode (add classes, divs, order, add/hide/remove fields, etc.) through the UI. I have found that managing what fields are displayed through code can be cumbersome if you have a lot. The view mode can handle a lot of what you need, but you need to enable the PDf view mode first.

Sample entity-print.html.twig

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>{{ title }}</title>
  {{ entity_print_css }}
</head>
<body>
  <div class="optional_class">
      {{ content }}
  </div>
</body>
</html>

Sample node--article--pdf.html.twig:

<article class="optional_class_wrapper">
  {{ content.field_name }}
  {{ content.body }}
  {{ label }} 
  {{ content.field_name.0.value }}
</article>
2

If you are writing a preprocess function, then the correct name of the function is THEMENAME_preprocess_entity_print(); replace THEMENAME with the machine name of the theme implementing it. If this is the case, what in the preprocess function you set as $vars['field_name'], where $vars is the array passed as reference to the preprocess function, it is accessible as {{ field_name }} in the Twig template file. See for example template_preprocess_node() and node.html.twig: What the function sets as $variables['node'] is available as {{ node }} in the template file.

Be sure to use the correct filename for the template.

4
  • Thanks for answering. When using THEMENAME_preprocess_entity_print(); I get an error "webserver is currently unable to handle this request.". Whereas if I use THEMENAME_template_preprocess_entity_print(); everything is running smoothly.
    – Aporie
    Aug 29, 2017 at 16:38
  • You need to check the server log to see what error you are exactly getting. THEMENAME_template_preprocess_entity_print() is not a preprocess function, though.
    – apaderno
    Aug 29, 2017 at 17:21
  • Yes, the preprocess function seems to be function THEMENAME_preprocess_entity_print__node__node_type(&$vars) (); so I changed the name of my twig template as entity_print__node__node_type.html.twig, but still impossible to get any values neither with $entity->get('field_name')->getValue(); neither with $node->get('field_name')->getValue(); I'm getting "Notice: Undefined index: node" in drupal log even if I load $node before with $node = \Drupal::routeMatch()->getParameter('node');
    – Aporie
    Aug 29, 2017 at 17:27
  • @Aporie this is also a good solution and I believe there is something else causing the error. I have provided my answer separately, but the template_preprocess_node() is the way to go if you enabled the PDF view mode Jan 23, 2018 at 19:35
1

I think this is the problem, you are trying to get the node from the route, only, you are not on a node route, you are on an entity_print route, so node is not available.

As a side note, you should always check that the field exists before trying to get the value. Before you try something like this:

$vars['field_name'] = $entity->get('field_name')->getValue();

You should do something like this:

if ($node->hasField('field_name') && !$node->field_name->isEmpty()) {
  $vars['field_name'] = $entity->get('field_name')->getValue();
}

But in this case, that probably wouldn't even prevent the error, since $node ( or $entity ) isn't even populated here.

What I've resorted to doing for entity_print preprocess functions is basically parsing the string URL. Your print path is something like /print/pdf/{entity_type}/{entity_id}, which contains all of the info you need.

/**
 * Implements HOOK_preprocess_entity_print__entity().
 */
function THEME_preprocess_entity_print__node(array &$variables) {
  $route = \Drupal::routeMatch();
  $entity_type = $route->getParameter('entity_type');
  $entity_id = $route->getParameter('entity_id');
  // double check that you are printing a node, not a view or something else.
  if ($entity_type == 'node') {
    $node = \Drupal::entityTypeManager->getStorage('node')->load($entity_id);
    if ($node->hasField('field_name') && !$node->field_name->isEmpty()) {
      $variables['field_name'] = $node->field_name->value;
    }
  }
}

Now you can access 'field_name' in your twig file just using {{ field_name }}, but once again, check that it's populated before trying to print or you could get another error.

entity-print.html.twig

{% if field_name %}
  {{ field_name }}
{% endif %}

Of course, this assumes 'field_name' is a single value field, not an entity_reference or other sort of complex field.

2
  • This answer is good :) However, theres no need to double check the entity type since its specified in the functions name. It would be pertinent if the preprocess was named THEME_preprocess_entity_print. Cheers
    – JFC
    Dec 11, 2019 at 22:51
  • Not sure if this changed over time, but shouldn't this line: $node = \Drupal::entityTypeManager->getStorage('node')->load($entity_id); actually be: $node = \Drupal::entityTypeManager()->getStorage('node')->load($entity_id);
    – Mark
    May 25, 2022 at 16:35

Your Answer

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

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