The Definitive Guide to Drupal 7

Theming forms with Template Files

Creating template files for forms is surprisingly easy given what you’ve already learned. As mentioned in the “First Steps for Theming Forms” section, you’ll need to open template.php and implement a hook_theme() function. Instead of just defining the render element, you’ll need to add two more things, as shown in Listing 16–30:

  1. A path key (optional) that contains the path to where the template file is located in your theme.
  2. A template key that contains the name of the template file, without the .tpl.php suffix.
Listing 16–30. hook_theme() implementation example for using templates with forms
  1. <?php
  2. /**
  3.   * Implements hook_theme().
  4.   */
  5. function mytheme_theme() {
  6. return array( 'contact_site_form' => array(
  7. 'render element' => 'form',
  8. 'path' => drupal_get_path('theme', 'mytheme') . '/templates',
  9. 'template' => 'contact-site-form',
  10. ),
  11. );
  12. }

After creating the hook_theme() function shown in Listing 16–30, you’ll need to create the template file. In this case, it’s located in the templates directory within your theme:


Once that’s complete, simply clear the cache and Drupal will begin using your template file.

If there’s nothing in your file to begin with, you’ll get a blank page where the form used to be. The first thing you should do is add this line back to the template file: <?php print drupal_render_children($form); ?>. This will get the entire form back, and even though you may not want to keep everything in the form, you need to print the contents of this at the bottom of the form to ensure everything works properly as we detailed in the “Using drupal_render_children() is a Must!” section.

Manipulating Form Elements in Template Files

For the sake of covering this topic in detail, let’s use the example from the Manipulating Form Elements in Theme Functions section. The code in Listing 16–31 represents the result of completing the following tasks:

  1. Changing the labels for the name and mail elements.
  2. Rendering the name and mail elements individually.
  3. Arranging your markup and individually rendered elements as you want them.
  4. Finally, printing drupal_render_children($form) at the bottom of the template.
Listing 16–31. contact-site-form.tpl.php implementation of the contact form
  1. <?php // Change the labels of the "name" and "mail" textfields.
  2. $form['name']['#title'] = t('Name');
  3. $form['mail']['#title'] = t('E-mail');
  4. ?>
  5. <?php // Render the "name" and "mail" elements individually and add markup. ?>
  6. <div class="name-and-email">
  7. <p><?php print t("We'd love hear from you. Expect to hear back from us in 1-2 business days.") ?></p>
  8. <?php print render($form['name']); ?>
  9. <?php print render($form['mail']); ?>
  10. </div>
  11. <?php // Be sure to render the remaining form items. ?> <?php print drupal_render_children($form); ?>

While there are slight differences, it’s mostly the same (with less PHP). All of the possibilities that apply in theme functions apply just as well in template files. The variables themselves are slightly different. In theme functions and preprocess functions, the name element would be located in $variables['form']['name']. In template files, that same variable would be $form['name']. This is done specifically to make Drupal’s monster arrays easier on template authors.

Keep Your Template Cleaner with Preprocess Functions

In our example of theming a form with a template file, the template is quite messy. The definition of a clean template file is one that contains hardly any logic and that simply prints variables and maybe an occasional IF statement. If you are dissatisfied with the appearance of the template file, this is a perfect opportunity to use preprocess functions. To make this really clean, you’d do the following in a preprocess function:

  1. Perform all modifications to the form array.
  2. Create any new variables.
  3. Render each field individually and provide easy variables for templates.

Of course, this is not something you’d want to do on every form on your site. However, it’s very useful and convenient for highly styled user-facing forms that you want to take extra care to get right, such as the login, registration, and contact forms. The process of doing this is very easy, as demonstrated in Listing 16–32 with the contact form.

Listing 16–32. Using a preprocess function to do the heavy lifting for the template
  1. <?php
  2. /**
  3.  * Implements hook_preprocess_contact_site_form().
  4.  */
  5. function mytheme_preprocess_contact_site_form(&$variables) {
  6. // Shorten the form variable name for easier access.
  7. $form = $variables['form'];
  9. // Change labels for the 'mail' and 'name' elements.
  10. $form['name']['#title'] = t('Name');
  11. $form['mail']['#title'] = t('E-mail');
  13. // Create a new variable for your note.
  14. $variables['note'] = t("We'd love hear from you. Expect to hear back from us in 1-2 business days.");
  16. // Create variables for individual elements.
  17. $variables['name'] = render($form['name']);
  18. $variables['email'] = render($form['mail']);
  19. $variables['subject'] = render($form['subject']);
  20. $variables['message'] = render($form['message']);
  21. $variables['copy'] = render($form['copy']);
  23. // Be sure to print the remaining rendered form items.
  24. $variables['children'] = drupal_render_children($form);
  25. }

Because you’ve done all the work in the preprocess function, the template file in Listing 16–33 is crispy clean. Adding markup and classes and moving elements around is a piece of cake, and it’s very easy to see what this template file does at first glance.

Listing 16–33. The result of using a preprocess function to provide a clean, minimal template for the contact form.
  1. <p class="note"><?php print $note; ?></p>
  2. <p><span class="form-required">*</span> <?php print t("Denotes required fields."); ?></p>
  3. <ol>
  4. <li><?php print $name; ?></li>
  5. <li><?php print $email; ?></li>
  6. <li><?php print $subject; ?></li>
  7. <li><?php print $message; ?></li>
  8. <li><?php print $copy; ?></li>
  9. </ol>
  10. <?php print $children; ?>

You are reading content from two chapters on Theme Development from The Definitive Guide to Drupal 7, written by Jacine Luisi and published by Apress on July 19, 2011. All rights reserved.