5

I'm trying to create a module which adds a page, the controller works but I cannot render a twig template for it.

The page layout is displayed without the page I created and this warning is reported in the logs:

"Theme hook eu_calendar not found."

but I do have the hook defined

This is the controller:

class EuCalendarController extends ControllerBase {

    public function index() {
        return [
            '#title' => 'my title',
            '#theme' => 'eu_calendar',
            '#description' => 'description test',
        ];
    }
}

Module file:

function eu_calendar_theme($existing, $type, $theme, $path) {
    return [
        'eu_calendar' => [
            'template' => 'index',
        ],
    ];
}

I also tried adding variables like

function eu_calendar_theme($existing, $type, $theme, $path) {
    return [
        'eu_calendar' => [
            'variables' => [
                'test_var' => NULL,
            ],
            'template' => 'index',
        ],
    ];
}

What am I missing here?

And do I need to configure anything with the regions, I want my module to be displayed in the content region by default...

Any documentation or tutorial is also welcome, I read a bunch of them none of them is explaining the options and details.

4
  • You are missing render element/variables. Template is redundant.
    – user21641
    Sep 29, 2017 at 8:16
  • @IvanJaros I tried adding variables, nothing changed. I want /modules/eu_calendar/templates/index.html.twig to be rendered so I thought 'template' => 'index' is about that...
    – madpoet
    Sep 29, 2017 at 8:20
  • You sure the file saved to the correct server?
    – No Sssweat
    Sep 30, 2017 at 9:34
  • I had saved the file as...mymodule.theme *facepalm* Just to clarify, it's supposed to be saved in the mymodule.module. Mar 27, 2018 at 1:16

3 Answers 3

2

myModule.module

function myModule_theme($existing, $type, $theme, $path) {    
return array(
 'pagina_3' => array(
   'variables' => array(
     'titulo' => 'title', 
     'descripcion' => 'description',
     'formulario'   => NULL
      ),
    'template' => 'pagina_3'
   )
  );


}

mymodule/templates/pagina_3.html.twig

<div class="row">

    <div class="col-md-6">
        <h2>{{ titulo }}</h2>
        <p>{{ descripcion }}</p>
    </div>

    <div class="col-md-6">
        {{ formulario }}
    </div>

</div>

myModuleController.php

public function verPagina3() {

    $form = $this->formBuilder()->getForm('Drupal\myModule\Form\InsertarGastoForm');

    // Le pasamos el formulario y demás a la vista (tema configurado en el module)
        return [
            '#theme' => 'pagina_3',
            '#titulo' => $this->t('Formulario crear empresa'),
            '#descripcion' => 'Formulario para crear una nueva empresa en Drupal 8',
            '#formulario' => $form
        ];


   }
1
  • 2
    '#titulo', '#descripcion', '#formulario'. It's news to me that Render Arrays allow using Spanish words as properties.
    – No Sssweat
    Sep 30, 2017 at 9:15
2

I guess I couldn't be able to clear the caches or something. I changed the hook name, uninstalled the module and installed it back, cleared the caches, restarted php-fpm and memcached etc. and it started working somehow.

For reference this is how theming works, may help other newcomers like me:

First the theme and the variables that needs to be passed is defined inside the *.module file. The trick is the variables key, without it Drupal ignores the definition.

The key of the array is also the name of the twig file by default, which can be overridden with template. So no need to pass template if it's the same with the key.

The theme definition to be rendered is defined inside the controller with #theme. Any variable that is not defined in the theme definition are not sent to the template even it's sent in the controller.

So the final working code is:

Module: (modules/eu_calendar/eu_calendar.module)

function eu_calendar_theme($existing, $type, $theme, $path) {
    return [
        'index' => [
            'variables' => [
               'featured' => [],
               'events' => [],
            ],
        ],
    ];
}

Controller: (modules/eu_calendar/src/Controller/EuCalendarController.php)

namespace Drupal\eu_calendar\Controller;

use Drupal\Core\Controller\ControllerBase;

class EuCalendarController extends ControllerBase {
    public function index() {
        return [
            '#theme' => 'index',
            '#events' => ['event1', 'event2'],
            '#featured' => ['featured1', 'featured2'],
        ];
    }
}

Template: (modules/eu_calendar/templates/index.html.twig)

<h3>Featured Events</h3>
<ul>
    {% for featured_event in featured %}
    <li>{{ featured_event }}</li>
    {% endfor %}
</ul>

<h3>Events</h3>
<ul>
    {% for event in events %}
    <li>{{ event }}</li>
    {% endfor %}
</ul>
4
  • I just had the same thing in a Drupal 10 site... I built and installed loads of the module without a .module file... And then added the file with a correct theme hook but the hook never fired... I wonder if Drupal caches that there is no module file during install and then forever doesn't look for one again during cache clears?
    – Nick
    Dec 20, 2022 at 9:49
  • I also experienced this in a Drupal 10 site. Some combination of repeatedly uninstalling and reinstalling the module, running cron and clearing the cache eventually fixed it. Clearing the cache was not, by itself, sufficient to fix the issue.
    – arnoldbird
    Jun 20 at 15:50
  • UPDATE: For me, the problem returns again on the next cache clear. Drupal can't see the template at times.
    – arnoldbird
    Jun 20 at 15:55
  • UPDATE-2: I had to change the name of my module to fix this. Now when I clear the cache, the problem doesn't come back.
    – arnoldbird
    Jun 20 at 16:26
1

This is the controller:

public function index()
{
    $build['myelement'] = array(
        '#theme' => 'eu_calendar',
        '#title' => 'my title',
        '#description' => 'description test',
    );
    return $build;
}

Module file:

function eu_calendar_theme($existing, $type, $theme, $path)
{
    return array(
        'euCalendar' => array(
            'template' => 'index',
            'path' => $path . '/templates',
            'variables' => array(
                'title' => NULL,
                'description' => FALSE,
            ),
        ),
    );
}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.