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?

Nic Cottrell
  • 9,401
  • 7
  • 53
  • 76
Cybercampbell
  • 2,486
  • 11
  • 48
  • 75
  • Is it intentional that the file is `myModuleBlock.php` but the class is `ModuleBlock` without the `my` ? Seems non-standard. – Nic Cottrell Jul 26 '16 at 07:58

2 Answers2

13

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.

Nicensin
  • 943
  • 1
  • 6
  • 15
  • 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. – Cybercampbell Jun 12 '16 at 12:58
  • 1
    I am pleased that I could help you. Thanks for your notices. I edited my answer. – Nicensin Jun 12 '16 at 15:56
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

acrosman
  • 12,814
  • 10
  • 39
  • 55
  • Awesome thanks, This is kinda working. How to I define the variables in the _theme function? – Cybercampbell Jun 05 '16 at 19:33
  • 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. – acrosman Jun 05 '16 at 20:27
  • Thanks @acrosman - The variables should be coming from the DB which are set via the block form. Or have I got this all wrong? – Cybercampbell Jun 05 '16 at 20:29
  • I updated the code example to show a little more clearly a couple ways to get at the values from the config form. – acrosman Jun 05 '16 at 20:42
  • 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. – Cybercampbell Jun 05 '16 at 20:54
  • Ok, I'm still doing something wrong. Now it doesn't work in either the Module or Theme directory. – Cybercampbell Jun 05 '16 at 20:58
  • You don't HAVE to put anything in that section. You can define some default values to make sure you have them when you reach the twig file if they aren't defined in the block instance. Also I made a small typo above (left off the # from the block's variable name). Beyond that it's hard to say what's happening in your project without updated code from your project. – acrosman Jun 05 '16 at 21:14