Drupal 8.9.6, I'm trying to create a custom module admin report page.

I have a custom sub theme of seven called wd_admin.

I made a page controller that generates a table as markup, but want to use a twig file to render the html, and can't figure out the theming.

It is using block.html.twig to render the content, and the first suggested template is block--wd-admin-content.html.twig. So I created it, and plumbed it in with hook_theme and hook_theme_suggestions_block_alter, but it affected the content on all admin pages, wrong move.

Seems like for this to work it would have to be specific to the page. What do I need to do to render this page, maybe a page.html template?

  • Yeah, you're doing it wrong. Can you post your controller's code?
    – No Sssweat
    Commented Oct 16, 2020 at 2:35
  • Thanks; too long to post so here's a gist. I have some test code to create a table, I want to instead send the variables to a twig template. gist.github.com/pglatz/4f2d826909124dfddbd9ba3f79a424ba
    – pglatz
    Commented Oct 16, 2020 at 14:42

2 Answers 2


Yeah I think you're conflating a few different concepts and making everything way more complex than it needs to be.

If you all you want to do is render a particular custom template with your controller then you'd want to:

// In fun.module
function fun_theme() {
  return [
    'a_fun_template' => [
      'variables' => [
        'heading' => '',
        'activities' => []

// Then in your controller
public function yourRenderMethod() {
  $heading = 'Some fun activities';
  $activities = [
     'Rocket League',
  return [
    '#theme' => 'a_fun_template',
    '#heading' => $heading,
    '#activities' => $activities, 

// Then in a-fun-template.html.twig
  Do whatever with your variables, like print them
<h1>{{ heading }}</h1>
{% for activity in activities %}
  <li>{{ activity }}</li>
{% endfor %}

EDIT: I think I figured out why you're looking at the block. All that that is is the "Main page content" block from the blocks page. This just renders the main content for the page, which in this case would be the contents of your controller's template. Now that said, what I wrote before was...

I really don't understand where the block is coming into play here, but I think you're misunderstanding that as well.

First, the default template suggestions are very general. block--wd-admin-content.html.twig is probably added by wd_admin to every admin block by default. That's why a template by that name would be used by all blocks in the admin area. Generally the longer the suggested template name, the more specific it is. Template suggestions that you add to hook_theme_suggestions_block_alter() will apply to all blocks unless you wrap the suggestion in conditional logic that says otherwise. If all you're doing is using a hook_theme template in a controller then you don't need this hook at all.

  • 1
    Edited to add some context about the main page content block
    – Mrweiner
    Commented Oct 16, 2020 at 23:13
  • Thanks, Mrweiner, your clear explanation was a big help. best, Phil
    – pglatz
    Commented Oct 17, 2020 at 21:48
  • Awesome, glad to hear it. Wold be great if you could mark one of the answers accepted just so that the bot doesn't necromance this for years. :)
    – Mrweiner
    Commented Oct 17, 2020 at 22:37

I found a pretty good solution here, no twig required: https://www.digitalnadeem.com/2019/12/13/how-to-create-a-custom-filter-form-and-update-custom-table-data-in-drupal/

I'm going to be presenting this with some options, so doing it in a form makes a lot of sense.

I'd still like to understand all that's involved with presenting twig templates better. I've been studying code in core, but a lot of what was done there is pretty complicated. It's well engineered and beautifully written, but I'm struggling to find all the parts involved in advanced theming.

Your Answer

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

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