I have followed the "hello world" module tutorial at https://www.drupal.org/developing/modules/8. At the end of the tutorial, you create a custom page which gets generated from a render array you created in the module's controller. The content is a single line of text, contained in the #markup field in the render array.

Now I'm trying to go beyond and create a more complex page, with some ajax-enabled elements. Hard-coding a bunch of HTML and Javascript into the #markup field does not seem to be the way to go. And looking through other modules, I see that most do not have a #markup field, but a bunch of other fields, some of which seem to be custom fields (possibly adhering to an unknown naming convention), and others which appear to be defined by Drupal core. But in some cases it's not clear which are which, and after hours of searching the Drupal documentation and the wider internet, I cannot find a clear explanation of how the different fields in the array are interpreted and translated into HTML. (It seems that "theme hooks" may be involved somehow, but it's not clear to me which hooks are needed or where those hooks should be defined)

Can someone provide or point me towards an explanation of how to get to a desired HTML layout and set of javascript behaviors using render arrays?

2 Answers 2


Drupal is build and designed around the idea that the markup produced by a module is themable (ie. it can be changed by a theme independently of the module). Which mean that markup for a page is usually build using Drupal theming system. Basically, you define templates then use them in your render arrays. In your render arrays, #theme define the used templates, almost ever other entries are specific to the templates and used to inject variables into the template or its preprocess functions.

To add CSS and JavaScript you need to attach them to your render arrays with #attached as assets libraries, see the Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module documentation for details. This is used to allow Drupal core and other module to optimize inclusion of the CSS and JS files into your page.

  • So #theme should contain the filename of a twig template?
    – duggulous
    Oct 29, 2015 at 19:01
  • #theme should be the name of the theme hook to use. The twig template for a theme hook, should be named after its name, with "_" replaced with "-". Nov 3, 2015 at 18:43

There's a naming convention at work here. Apparently the convention is "'base_hook_name__sub_hook_name'." I don't know what "base_hook_name" or "sub_hook_name" mean, but I do know that if you create a module called mymod and create a function in mymod.module named mymod_theme(), Drupal will find it and use it to theme your module.

mymod_theme() should return an array of what I'll call "theme arrays" which are arrays containing things like the name of the template to use, and the variables that will get delivered to the template. The possible fields in these arrays are documented at https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_theme/8

'template' is one of the fields, and can be used to specify the twig template to use.

So continuing with the mymod example,

in mymod/mymod.module:

    return array(
        'mymaintheme' => array(
            'template' => 'mymodtemplate',  //corresponds to templates/mymodtemplate.twig.html
            'variables' => array(           //the template file will use these variables
                'title' => NULL             //we define the variable names and assign NULL
                                            //(optionally, we could assign a default value instead).  
                                            //The actual values will be populated from the 
                                            //render array that our controller will create


        'someothertheme' => array(
            'template' => 'adifferenttemplate',  
            'variables' => array(                   
                'aVariableInMyTemplate' => NULL
                'anotherVariable' => NULL

in mymod/src/Controller/mymodController.php

public function thisGeneratesContent(){
    return array(
        '#theme' => 'mymaintheme',  //matches one of the themes returned from mymod_theme()
        '#title' => t('My Module')  //we defined a variable in our theme called 'title' so this value 
                                    //gets passed to the template file, where it replaces instances of {{title}}

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.