Drupal 8 Use Suggested Template When Programmatically Rendering Node

Drupal 8 Use Suggested Template When Programmatically Rendering Node

I'm rendering a node programmatically from within a Block class in a Drupal 8 module and I would like to be able to use one of the suggested template names I get in the generated DOM to override how the node is rendered.

Unfortunately, any suggested name I use to create the template in my templates folder is ignored and Drupal renders the basic bartik node.html.twig template.

Here are the relevant parts of the code :

<?php

/**
  * @Block
  */


/**
  * {@inheritdoc}
  */
public function build()
{
    $events = [];
    $eventNodes = $this->repository->findBy(['status' => 1], [ 'field_date' => 'ASC' ]);
    $viewBuilder = $this->entityManager->getViewBuilder('node');
    foreach ($eventNodes as $eventNode) {
        $event = EventMapper::fromNodeToEvent($eventNode, [
            'title' => 'field_titre',
            'start' => 'field_date',
            'end'   => 'field_fin'
        ]);

        $build = $viewBuilder->view($eventNode, 'full');
        $event['html'] = $this->renderer->renderRoot($build);

        $events[] = $event;
    }

    $months = [];
    if (count($events) > 0) {
        $indexer = new EventIndexer($events);
        $months = $indexer
            ->indexByMonths()
            ->getResults()
        ;
    }

    return [
        '#theme' => 'calendar_block',
        '#events' => $events,
        '#attached' => [
            'library' => ['calendar/calendar'],
            'drupalSettings' => [ 'events' => $events, 'monthsIndex' => $months ]
        ]
    ];
}

/**
* Custom finder in a repository service. get list of nids and load
* them.
*/

/**
  * @param array $criteria
  * @param array $orderBy
  * @param int   $limit
  * @param int   $offset
  *
  * @return array<Node>
  */
public function findBy(array $criteria = [], array $orderBy = [], $limit = null, $offset = 0)
{
    $query = $this->queryFactory->get('node');
    $query->condition('type', self::TYPE);
    foreach ($criteria as $field => $value) {
        $query->condition($field, $value);
    }

    if (!empty($orderBy)) {
        foreach ($orderBy as $field => $direction) {
            $query->sort($field, $direction);
        }
    }

    if (!is_null($limit)) {
        $query->range($offset, $limit);
    }

    $nids = $query->execute();
    $events = $this->etm->getStorage('node')->loadMultiple($nids);

    return $events;
}

/**
  * Twig fragment where the rendered event is printed.
  *
  */

{% for event in events %}
    <div class="js-calendar-slider-event calendar-slider-event" data-start="{{events[loop.index0].start|date('Y-m-d') }}" data-end="{{events[loop.index0].end|date('Y-m-d') }}">{{ event.html }}</div>
{% endfor %}

1 Answer

You have to create a theme suggestions hook by hook_theme()

like i run a test case for you, i have write a hook_theme()

in my module file here is code

/**
 * Implements hook_theme().
 */
function my_module_theme($existing, $type, $theme, $path) {
  $theme = array();
  $theme['node__contentTypeName'] = array(
    'render element' => 'content',
    'base hook' => 'node',
    'template' => 'node--contentTypeName',
    'path' => drupal_get_path('module', 'my_module') . '/templates',
  );
  return $theme;
}

then place your template twig file in my_module/templates folder

here is my block code

namespace Drupal\my_module\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
 * Provides a 'example node render block' Block
 *
 * @Block(
 *   id = "example_node_render_pulgin_block",
 *   admin_label = @Translation("example render node"),
 * )
 */
class ExampleNodeRenderBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {

    $nid = 36;
    $entity_type = 'node';
    $view_mode = 'full';
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity_type);
    $storage = \Drupal::entityTypeManager()->getStorage($entity_type);
    $node = $storage->load($nid);
    $build = $view_builder->view($node, $view_mode);
    $output = render($build);

    return array(
      '#type' => 'markup',
      '#markup' => $output,
    );
  }
}

i have add some extra code in twig file to make sure my template is rendering or not

this is the line i have add in my template.twig

<div><h1>hello its me</h1></div>

and finally i place my block some where and here is result

Hope this solve your problem

Thanks

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.

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.