8

I have a custom Module that creates a custom Block which has field elements.

This all works fine but I need to theme this block. I have checked the other posts on here and tried with no luck.

I have enabled twig debug and got theme suggestions. Still no luck.

Can anyone please point me in the right direction.

This is what I have so far:

my_module/my_module.module

// nothing related in here

my_module/src/Plugin/Block/myModuleBlock.php

<?php

namespace Drupal\my_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'ModuleBlock' block.
 *
 * @Block(
 *  id = "module_block",
 *  admin_label = @Translation("My Module"),
 * )
 */
class ModuleBlock extends BlockBase {

  public function blockForm($form, FormStateInterface $form_state) {
    $form['test'] = array(
      '#type' => 'select',
      '#title' => $this->t('test'),
      '#description' => $this->t('test list'),
      '#options' => array(
        'Test' => $this->t('Test'), 
      ),
      '#default_value' => isset($this->configuration['test']) ? $this->configuration['test'] : 'Test',
      '#size' => 0,
      '#weight' => '10',
      '#required' => TRUE,
    );    
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['test'] = $form_state->getValue('test');
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build = [];
    $build['module_block_test']['#markup'] = '<p>' . $this->configuration['test'] . '</p>';
    return $build;
  }


}

my_module/templates/block--my-module.html.twig // as suggested by twig debug

<h1>This is a test</h1>
<div id="test-widget">{{ content }}</div>

I should also note that in my my_theme.theme I have this but I don;t think its relevant:

// Add content type suggestions.
function my_theme_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  if ($node = \Drupal::request()->attributes->get('node')) {
    array_splice($suggestions, 1, 0, 'page__node__' . $node->getType());
  }
}

As for what I've tried is this:

public function build() {
    return array(
      '#theme' => 'block--my-module'
    );
}

But still no go.

Any help here is very much appreciated.

UPDATE: So I just got it to work but I still need help. I moved the template block--my-module.html.twig to my theme directory and it worked.

How do I get it to work in my module directory?

1
  • Is it intentional that the file is myModuleBlock.php but the class is ModuleBlock without the my ? Seems non-standard. Commented Jul 26, 2016 at 7:58

2 Answers 2

14

UPDATE: So I just got it to work but I still need help. I moved the template block--my-module.html.twig to my theme directory and it worked.

How do I get it to work in my module directory?

You can create a directory called templates/ in your modules root. Place your template here.

Now let Drupal know you store the template in your module. in your_module.module add this function:

function YOUR_MODULE_theme($existing, $type, $theme, $path) {
  return array(
    'block__my_module' => array(
      'render element' => 'elements',
      'template' => 'block--my-module',
      'base hook' => 'block'
    )
  );
}

This is not tested. It´s the way it worked for my custom block.

Don´t forget to clear the cache.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Nicensin - Marking as accepted answer but please correct the following. 1) replace $pat with $path 2) remove .html.twig from the template variable. That way others can benefit from your answer.
I am pleased that I could help you. Thanks for your notices. I edited my answer.
7

To be able to add the twig file in your module, you need to make sure the module defines the reference, not the theme.

You can still implement hook_theme() in the module's .module file as follows:

function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'mymodule_block'     => [
      'variables' => [
        // define defaults for any variables you want in the twig file
        'attributes' => [
           'class' => ['my-module-class'],
         ], //etc
      ],
    ],
  ];
}

Then in your block's build() implementation you can add a reference to the new theme function:

public function build() {
    // Load the configuration from the form
    $config = $this->getConfiguration();
    $test_value = isset($config['test']) ? $config['test'] : '';

    $build = [];
    $build['#theme'] = 'mymodule_block';

    // You would not do both of these things...
    $build['#test_value'] = $test_value;
    $build['module_block_test']['#markup'] = '<p>' . $test_value . '</p>';

    return $build;
}

Finally be careful about where you place your twig file and what you name it. Create a templates directory in your module directory, and replace the _ in the theme function name with -: mymodule-block.html.twig

7 Comments

Awesome thanks, This is kinda working. How to I define the variables in the _theme function?
The theme function allows you to set defaults (I've never fed it NULL so it's possible that doesn't get passed to the twig file, which is to say it is probably "working" as designed with what you're doing). You set the variables you want during render in the block's build() method. You may also find the kint() function from devel's submodule of the same name helpful to check what's actually arriving in the template.
Thanks @acrosman - The variables should be coming from the DB which are set via the block form. Or have I got this all wrong?
I updated the code example to show a little more clearly a couple ways to get at the values from the config form.
But what do I put in this section: ` // define defaults for any variables you want in the twig file`? Please note that is all working as it was when the twig file was in my theme folder. It was getting the variables from the form.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.