4

I'm trying to upgrade old Drupal 7 modules to 8 and I am struggling to figure out how to create a blank page (by this I mean, a page with zero HTML from enabled themes) for my module. I added routing to my custom controller, my controller method takes care of all the logic and returns the following array:

[
        'showVideo' => [
            '#theme' => 'videoPage',
            '#content' => $content
        ]
]

I already defined "videoPage" in mymodule.module using hook_theme:

Function mymodule_theme($existing, $type, $theme, $path){
  return array(
    'videoPage' => array(
      'variables' => array('content' => NULL),
      'file' => 'mymodule.html.twig'
    )
  );
}

"mymodule.html.twig" is a full stand-alone HTML file from the opening HTML tag to the closing tag. I don't want any other content to show up there but instead I'm getting the content in that Twig file, then followed by the HTML for the currently selected Drupal theme. Also, my {{ content.value }} calls in Twig seem to be getting ignored. And by this I mean, I can literally see {{ content.xyz }} in the markup being printed. The $content being returned by the controller is an array and I'm sure all the values are set. It almost feels like the Twig file is being called while the Controller's logic is being ignored. (this last bit has been solved by Clive's response)

Any help? Am I totally off in this approach?

  • I noticed that if in my Controller I return a Response object then I will be able to get a blank page. Perhaps I need to render the Twig template using the variables generated on my Controller, set the rendered HTML as the content of my Response object, and return that Response object? – hanyuxuan Dec 9 '15 at 15:11
  • I don't understand what you are trying to do in your question, but you are right in your comment. You can use a Response object to return any html from a controller, without anything added by drupal. – 4k4 Dec 10 '15 at 10:51
  • Basically, I need to return a Response object with only the HTML generated from the ONE Twig template I defined earlier using hook_theme. When people visit this custom page, the controller will send the user only the HTML generated from that Twig template and nothing else. – hanyuxuan Dec 10 '15 at 13:02
  • OK, now i know what you are trying to do, see my answer. – 4k4 Dec 10 '15 at 15:21
6

You can output the html of one twig only in a symfony response:

use Symfony\Component\HttpFoundation\Response;

public function my_page_controller() {

  $build = array(
    'page' => array(
      '#theme' => 'videoPage',
      '#content' => $content,
    ),
  );
  $html = \Drupal::service('renderer')->renderRoot($build);
  $response = new Response();
  $response->setContent($html);

  return $response;
}
2

The file parameter is:

The file the implementation resides in.

That should be used if you're creating a theme function, rather than template, and it will contain the path to the file that function is in.

What you're looking for is the template parameter:

If specified, the theme implementation is a template file, and this is the template name. Do not add 'html.twig' on the end of the template name. The extension will be added automatically by the default rendering engine (which is Twig.)

(emphasis mine)

So your implementation might look something like this:

function mymodule_theme($existing, $type, $theme, $path){
  return array(
    'videoPage' => array(
      'variables' => array('content' => NULL),
      'template' => 'mymodule'
    )
  );
}

Assuming "mymodule.html.twig" is in the root of your module's folder.

In case you're interested in why your current implementation is doing what it's doing: as you've provided a file, Drupal performs an include on it, and anything not within <?php tags gets written straight out to the buffer.

Source

  • Thanks for your quick response. The changes you suggested have fixed all the problems I was having with Twig. Twig is now being parsed and my variables (generated in my controller) are displaying correctly. But I'm still having the problem where the page is still displaying Drupal theme wrappers. My Twig file was supposed to be a standalone HTML page so I would like to make it so that's the only thing printed out by Drupal. Is there a way to remove the other theme templates on this custom page? HTML / Page etc..? – hanyuxuan Dec 8 '15 at 19:32
  • Using mixed case in a hook_theme might just confuse things. If you leave out template it will just convert your hook_theme template_name to template-name.html.twig. I'm probably not explaining well but most of core doesn't specify 'template' and it's good to follow that convention. Keeps things much more straightforward. – Cottser Dec 26 '15 at 13:51
  • I prefer to be explicit personally @Cottser (probably something I get from Python). I'd rather know in 6 months that I specifically intended to use a template file rather than a theme function with the same name - it sits better with my brain :) Convention is cool, I like that too, but too rigidly following someone else's ideas can slow you down in my experience – Clive Dec 26 '15 at 14:51
  • Sorry I wasn't clear. The convention I was talking about was to use the same template name as your hook_theme key. If you want to include 'template' go for it :) – Cottser Dec 26 '15 at 20:03
  • My fault @Cottser, one too many xmas White Russians probably! That makes perfect sense – Clive Dec 26 '15 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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