1

I'm using the following code to render a set of blocks programmatically:

$region_content = [];
$block_manager = \Drupal::service('plugin.manager.block');
$blocks = $this->getBlocks();
foreach ($blocks[$region_name] as $key=>$block_config) {
  $instance = $block_manager->createInstance($block_config['plugin_id'], $block_config['config']);
  $region_content[] = [
    $instance->build();
  ];
}

The contents of $block_config['config'] look like this:

[
  'provider' => 'search',
  'admin_label' => '',
  'label' => 'Search form',
  'label_display' => TRUE,
  'third_party_settings' => [
    'block_aria_landmark_roles' => [
      'role' => '',
    ],
  ],
]

The resulting $instance object seems to work correctly, and when I render $region_content I do indeed get the contents of the blocks as expected. But they are not wrapped in the block template. I thought I might have to do something like this:

$region_content[] = [
  '#theme' => 'block',
  'contents' => $instance->build(),
];

...but that doesn't work at all. How do I take this $instance object and render it using the standard block template? Or am I completely off course here?

1
  • Are these the correct variables for theming?
    – Kevin
    Nov 16, 2017 at 15:03

2 Answers 2

1

Yes, you need a render element with #theme = block, but this looks more like this example:

$build = [
  '#theme' => 'block',
  '#attributes' => [],
  '#contextual_links' => [
    'block' => [
      'route_parameters' => ['block' => $entity->id()],
    ],
  ],
  '#weight' => $entity->getWeight(),
  '#configuration' => $configuration,
  '#plugin_id' => $plugin_id,
  '#base_plugin_id' => $base_id,
  '#derivative_plugin_id' => $derivative_id,
  '#id' => $entity->id(),
  '#pre_render' => [
    static::class . '::preRender',
  ],
  '#block' => $entity,
];

You don't need to build this yourself, better use the view builder (where this code is from):

$build = \Drupal::entityTypeManager()->getViewBuilder('block')->view($block);

Where $block is the entity of the configured block:

$block = \Drupal::entityTypeManager()->getStorage('block')->load($block_id);

To get all configured blocks of a region see How to get block layout programmatically?

1
  • I think I may be thinking all wrong about how to store and manage my blocks. (I'm just storing the block config form data in the parent entity, and building the block on the fly from that info when it's time to render the parent.) Perhaps it would be better just to create and save a normal block with no region set, which (I think) should allow me to use the method you describe. Thanks for the help!
    – WRD
    Nov 16, 2017 at 15:46
2

If you want to render blocks directly from twig you can use:

Twig tweak 8.x-1.9 https://www.drupal.org/project/twig_tweak

You just need to install it. The block should be configured on "admin/structure/block" page. Example how to use: <dt>Block:</dt> <dd>{{ drupal_block('system_powered_by_block') }}</dd>

Add this code directly in the twig template file.

1

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.