1

I am creating a module that will allow editors to display nodes as "cards" using the summary from the node for the card text and a field (field_hero) as a background image to the card, the user can then click-thru to the actual content from the card. The editor can also define, via the layout builder the colour behind the text for the card and also where the text appears (top, left, right, bottom).

If I add several of these cards to a page using the layout builder, all of the cards use the values for position and colour from the last instance placed on the page.

My code block plugin code is:

  public function build() {
if ($entity_id = $this->configuration['entity']) {
  if (($entity = $this->entityStorage->load($entity_id)) && $entity->access('view')) {
    $render_controller = \Drupal::entityTypeManager()->getViewBuilder($entity->getEntityTypeId());
    $view_mode = isset($this->configuration['view_mode']) ? $this->configuration['view_mode'] : 'default';

    if (isset($this->configuration['card_colour'])) {
      $entity->card_colour = $this->configuration['card_colour'];
    }
    if (isset($this->configuration['card_layout'])) {
      $entity->card_layout = $this->configuration['card_layout'];
    }

    return $render_controller->view($entity, $view_mode);
  }
}

return [];

}

And my twig template is (ignore the empty url() in the style attribute):

{%
    set classes = [
        'node-card',
        'card-' ~ node.card_layout|clean_class,
        node.card_colour|clean_class,
        'clearfix'
    ]
%}
<article{{ attributes.addClass(classes) }}>
    <div{{ content_attributes.addClass('bg-img', 'clearfix') }} style="background-image: url()">
        <div class="summary">
            {{ content.body }}
        </div>
    </div>
</article>
0

$render_controller->view() invokes hook_ENTITY_TYPE_view() and this would be a better place to add custom values to the entity view.

Although probably not good practice you could get your approach working by cloning the entity before modifying the field values:

$entity = clone $entity;

In any case you need to adjust caching so that you store for each variant a different cache item in the render cache. For example by adding cache keys to the build array before returning it:

$build = $render_controller->view($entity, $view_mode);
if (isset($entity->foo)) {
  $build['#cache']['keys'][] = $entity->foo;
}
return $build;
3
  • Thanks for the answer. The clone method doesn't seem to change anything. I am at a loss to see how I can use the hook method as the values I need to add to the node are held in the layout builder block configuration, which would not be accessible in the hook_ENTITY_TYPE_view.
    – Scot
    Jun 17 '19 at 12:59
  • The clone method shows no results because there might be a second problem with the render cache, see the edit.
    – 4k4
    Jun 17 '19 at 13:52
  • Thanks 4k4 - I had already started down the path of the cache keys, I'm wrestling with cache contexts now! At least I now know where I'm going.
    – Scot
    Jun 17 '19 at 15:28

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.