2

Let's assume you have a "product" node $node, and for some reason you want to render HTML from $node into a variable $html using a Twig template. I'm a bit desperate yet, what would you do?

Additional info 1: We are not in a controller, but in a simple class that is registered as a service.

Additional info 2: 4k4 's answer does work if I call my class from a controller. But as soon I call it from a Drupal Console command I get an Exception "The theme implementations may not be rendered until all modules are loaded."

Edit: The complete solution

Obviously not all modules are loaded if we call the service inside a Drupal Console command. The Theme Manager will honor this with the aforementioned exception, so we have to force load the modules:

\Drupal::moduleHandler()->loadAll(); // Load all modules if not loaded already

Now it's safe to call the renderPlain() method as suggested below:

$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$build = $view_builder->view($node, $view_mode, $langcode);
$html = \Drupal::service('renderer')->renderPlain($build);

Edit: But what about a full page?

If you intend to render not only the node content but a full page (from <html> to </html>) you have to have the kernel handle an appropriate sub-request .

4

To render a plain node view, for example for emails, use this code:

$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$build = $view_builder->view($node, $view_mode, $langcode);
$html = \Drupal::service('renderer')->renderPlain($build);

If you want to customize the output, use a special view mode and a template node--[view-mode].html.twig.

Edit: Full page

You can build more complex render arrays:

  $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
  $content = $view_builder->view($node, $view_mode, $langcode);
  $build = [
    '#type' => 'html',
    'page' => [
      '#type' => 'page',
      '#theme' => 'page',
      '#title' => 'Title',
      'content' => $content,
    ],
  ];

  $html = \Drupal::service('renderer')->renderPlain($build);

This is only a basic version of a page, if you want the full version with all features like attachments and libraries you need a request on Drupal.

  • I am getting an Exception: "The theme implementations may not be rendered until all modules are loaded". I have seen this many times today. Maybe this has something to do with the fact that my code is called by a console command, but I'm totally stuck here. – jensjensen Dec 20 '16 at 16:44
  • Ok, tested it, it just works if I call it from a controller. But how can I do the same in a console command? – jensjensen Dec 20 '16 at 16:52
  • Don't know what you are trying to do, but just dropped it in a drush script and it works. – 4k4 Dec 20 '16 at 16:58
  • Not to use drush is a project requirement, I have to use drupal/console instead. I hope it is just an incompatibility between the current console (1.0.0-rc11) and core (8.2.4) versions. – jensjensen Dec 20 '16 at 17:25
  • Figured it out, pls see the "complete solution" section above. – jensjensen Dec 21 '16 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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