I'm struggling with understanding theming pages with templates. I'm stuck with creating a new template for a programmatically created page. I have a module that shows a download page for a file. The page is basically a form where user can click Submit and get their file downloaded. I construct the whole form programmatically in a page callback. But what if I want to style it with a template? I fail to see how to do it. Here is my (simplified) code:

// Implements hook_menu()
function mymodule_menu()
    $items = array();    
    $items['file/%mymodule_mycustomfile/download'] = array(
    'page callback' => '_mymodule_filedownload',
    'title' => 'Page Title',
    'page arguments' => array(1),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
    return $items;

// Implements autoloader %mymodule_mycustomfile
function mymodule_mycustomfile_load($fid)
    return ($fid > 0) ? (object)array('fid' => $fid) : FALSE;

// Page callback function
function _mymodule_filedownload($mycustomfile)
    return drupal_get_form('_mymodule_filedownload_form', $mycustomfile);

// Creates page form
function _mymodule_filedownload_form($form, &$form_state, $mycustomfile)
    $form['label'] = array('#type' => 'item', '#markup' => 'File ID');
    $form['fid'] = array('#type' => 'item', '#markup' => $mycustomfile->fid);
    $form['submit'] = array('#type' => 'submit', '#value' => 'Download');
    return $form;

// Submit button click handler
function _mymodule_filedownload_form_submit($form, &$form_state)
    die('On Submit');

You can see that I construct my form fully in _mymodule_filedownload_form(). But I want to have something like file-download.tpl.php for it and put things like Label there. I fail to see how to do it. My problems are:

1) I stumbled upon theme_hook_suggestions and by default Drupal suggests the following template names: page__file, page__file__%, page__file__1, page__file__download. When I created page--file--download.tpl.php and went to /file/1/download, my screen went blank. I do not know how to output my form in this file and I'm afraid I do not even want to restyle the whole page. I only need to style the page content (the form itself) and leave the page alone. Why can't I have file--download.tpl.php if I have node.tpl.php and comment.tpl.php?

2) As a side note, when you execute template_preprocess_page(&$variables) on node pages, you can see the defined $variables['node'] that contains full node object. How is it done? Can I possibly have something like $variables['mycustomfile'] on my file download pages?


In this case your page is a form, so you need to create a form template this way:

Implement hook_form_alter() in a module or template.php and set the form's #theme property:

function _mymodule_filedownload_form($form, &$form_state, $mycustomfile)
    $form['#theme'] = array('mymodule_filedownload_form');


Then implement new theme:

 * Implements hook_theme().
function hook_theme($existing, $type, $theme, $path){
  $path = drupal_get_path('module', 'mymodule');
  return array(
    'mymodule_filedownload_form' => array(
      'render element' => 'form',
      'template' => 'form--mymodule_filedownload_form',
      'path' => $path . '/templates',

And then add form--mymodule_filedownload_form.php template with follow code to render complete form (you can render it also by components):

<?php print drupal_render_children($form) ?> 
| improve this answer | |
  • thanks. I managed to figure out most of your solution myself, but what I lacked was $form['#theme'] = array('mymodule_filedownload_form'); Now I can use a template. – Ari Linn Dec 24 '14 at 3:19

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.