7

Ok, so I know blocks in Drupal 8 have these things called "contexts" which allow Core to clear cache on a fine-grained basis. I can't find any decent explanation of how they work, or how to get page variables from them or whatever.

My goal is to have a block type that renders fields or a display mode of the current node into the block content. I have seen elsewhere how one would get the current node, but I don't entirely understand how it's supposed to feed back into cache contexts. I know #cache on render arrays exist, but there's also a bunch of methods from ContextAwarePluginInterface that I'm not sure what they do. Is there some documentation I'm missing?

  • You could create a view block and do it that way. I haven't played around much with D8 normal blocks. The only way would be if they allow you to pass some sort of contextual filter to the block. – No Sssweat Nov 15 '15 at 3:56
9

There are two completely different kinds of contexts.

Cache contexts, which have nothing to do with this. They're not used to invalidate something, but vary by something (e.g. cache differently for different user permisisons). Cache tags are for invalidation.

What you mean are plugin contexts. And yes, blocks are able to use them since a short while (They always could, but the block.module didn't support it properly). As @larowlan said, core uses them mostly for visibility conditions but it works the same for blocks.

One such example that you can look at is the NodeType condition. What you need to do is add the context annotation and then you can use it as $this->getContextValue('node'). The advantage of this is that your block is more flexible and doesn't need to know where the node is coming from exactly, that's up to the user configuring it.

Note that this is not visible in the UI currently unless there is actually more than one node to chose from.

| improve this answer | |
  • Great explanation, the plugin context is about visibility. Libertardian should use a view block, as NoSssweat explained in the comment on the question. This will be invisible, if no node is in the current route, so context is not needed for the task. – 4k4 Nov 15 '15 at 9:07
  • No, plugin context is not only about visibility.Condition plugins are just one type of plugins that can use conditions. Any type of plugin can be made to work with them. Core just doesn't use it for that, but it works perfectly fine. I'm using it a lot together with page manager for example. – Berdir Nov 15 '15 at 9:09
  • See drupal.org/node/2287073 for a core issue that adds context to views blocks. That for example allows the same views block to filter by a context, without hardcoding it to default to the current node. Again, very useful in page manager, where you can e.g. use the same views block to show content for different terms. – Berdir Nov 15 '15 at 9:11
  • That is interesting, you can do a lot more with the plugin context. Coming from drupal 7 I would use a view block with a contextual filter to display fields of the current node. What is the drupal 8 way to do this? – 4k4 Nov 15 '15 at 9:17
  • I've read the core issue. Now I understand. The contextual filter in views is now based on the plugin context, so when the end user uses this in views, this is done with plugin context in the background. Otherwise it would not work in drupal 8 now. Great work. – 4k4 Nov 15 '15 at 9:39
8

For using node in block, i use context. For example: this block display links for edition and deleting current node:

/**
 * @file
 * Contains \Drupal\my_module\Plugin\Block\NodeMenuBlock.
 */

namespace Drupal\my_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Link;
use Drupal\Core\Url;

/**
 * @Block(
 *   id = "node_menu_block",
 *   admin_label = @Translation("Node Menu Block"),
 *   category = @Translation("My Group"),
 *   context = {
 *     "node" = @ContextDefinition(
 *       "entity:node",
 *       label = @Translation("Current Node")
 *     )
 *   }
 * )
 */
class NodeMenuBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {
    $node = $this->getContextValue('node');
    $nid_fld = $node->nid->getValue();
    $nid = $nid_fld[0]['value'];

    $markup = '';
    $links = ['entity.node.edit_form' => 'Edit', 'entity.node.delete_form' => 'Delete', ];
    foreach($links as $rout=>$text) {
      $url = Url::fromRoute($rout, array('node' => $nid));
      $link = Link::fromTextAndUrl(t($text), $url)->toRenderable();
      $link['#attributes'] = array('class' => array('button', 'button-action'));
      $markup .= render($link).' ';
    }

    $block = [
      '#type' => 'markup',
      '#markup' => $markup,
    ];
    return $block;
  }

}
| improve this answer | |
1

The context aware plugin stuff is mainly used by block visibility conditions. E.g see the node condition which takes the current node. I'm not sure if blocks per-se can hook into this. I can say for certain that you can use the route match service and get the current node, should it exist, from that.

| improve this answer | |
0

Check out the Block node contrib module: https://www.drupal.org/project/block_node

Introduction

This module provides a block which can display either the current node or a specified node in a given view mode.

Possible uses

I want to display a specific node in a sidebar region using a teaser view mode. I want to display a list of teaser nodes referenced by an entity reference field on the current node.

Installation

Install as usual, ideally with composer. Enable the module.

Configuration

Place the block using the block layout page as you normally would to place any block.

Configuration options:

Use current node

  • When checked the current node will be displayed in the block if the block is placed on a node page.

Node to display

  • Search for a node to display. When selected this node will be displayed in the block.

View mode

  • Choose the view mode from the available options. The node displayed in the block will be displayed in this view mode.
  • Other settings are the standard block settings.
| improve this answer | |

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.