theming_example.module

  1. drupal
    1. 8
    2. 7

Explains how a module declares theme functions, preprocess functions, and templates.

The underlying approach is that a module should allow themes to do all rendering, but provide default implementations where appropriate.

Modules are also expected to leave data as render arrays as long as possible, leaving rendering to theme functions and templates.

Functions & methods

NameDescription
template_preprocess_theming_example_text_formImplements template_preprocess() to add information to the theming_example_text_form().
theme_theming_example_content_arrayTheme a simple content array.
theme_theming_example_listTheming a simple list.
theme_theming_example_select_formTheming a simple form.
theming_example_list_pageAn example page where the output is supplied as an array which is themed into a list and styled with css.
theming_example_menuImplements hook_menu().
theming_example_pageInitial landing page explaining the use of the module.
theming_example_select_formA simple form that displays a select box and submit button.
theming_example_select_form_submit
theming_example_text_formA simple form that displays a textfield and submit button.
theming_example_text_form_submit
theming_example_themeImplements hook_theme().
View source
<?php

/**
 * @file
 * Explains how a module declares theme functions, preprocess functions, and
 * templates.
 *
 * The underlying approach is that a module should allow themes to do all
 * rendering, but provide default implementations where appropriate.
 *
 * Modules are also expected to leave data as render arrays as long as possible,
 * leaving rendering to theme functions and templates.
 */

/**
 * Implements hook_menu().
 *
 * The @link menu_example.module Menu Example @endlink provides extensive
 * examples for hook_menu().
 */
function theming_example_menu() {
  $items['examples/theming_example'] = array(
    'title' => 'Theming Example',
    'description' => 'Some theming examples.',
    'page callback' => 'theming_example_page',
    'access callback' => TRUE,
    'access arguments' => array('access content'),
  );
  $items['examples/theming_example/theming_example_list_page'] = array(
    'title' => 'Theming a list',
    'page callback' => 'theming_example_list_page',
    'access arguments' => array('access content'),
    'weight' => 1,
  );
  $items['examples/theming_example/theming_example_select_form'] = array(
    'title' => 'Theming a form (select form)',
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('theming_example_select_form'),
    'access arguments' => array('access content'),
    'weight' => 2,
  );
  $items['examples/theming_example/theming_example_text_form'] = array(
    'title' => 'Theming a form (text form)',
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('theming_example_text_form'),
    'access arguments' => array('access content'),
    'weight' => 3,
  );

  return $items;

}

/**
 * Implements hook_theme().
 *
 * Defines the theming capabilities provided by this module.
 */
function theming_example_theme() {
  return array(
    'theming_example_content_array' => array(
      // We use 'render element' when the item to be passed is a self-describing
      // render array (it will have #theme_wrappers)
      'render element' => 'element',
    ),
    'theming_example_list' => array(
      // We use 'variables' when the item to be passed is an array whose
      // structure must be described here.
      'variables' => array(
        'title' => NULL,
        'items' => NULL,
      ),
    ),
    'theming_example_select_form'  => array(
      'render element' => 'form',
    ),
    'theming_example_text_form'  => array(
      'render element' => 'form',
      // In this one the rendering will be done by a tpl.php file instead of
      // being rendered by a function, so we specify a template.
      'template' => 'theming_example_text_form',
    ),
  );
}
/**
 * Initial landing page explaining the use of the module.
 *
 * We create a render array and specify the theme to be used through the use
 * of #theme_wrappers. With all output, we aim to leave the content as a
 * render array just as long as possible, so that other modules (or the theme)
 * can alter it.
 *
 * @see render_example.module
 * @see form_example_elements.inc
 */
function theming_example_page() {
  $content[] = t('Some examples of pages and forms that are run through theme functions.');
  $content[] = l(t('Simple page with a list'), 'examples/theming_example/theming_example_list_page');
  $content[] = l(t('Simple form 1'), 'examples/theming_example/theming_example_order_form');
  $content[] = l(t('Simple form 2'), 'examples/theming_example/theming_example_text_form');
  $content['#theme_wrappers'] = array('theming_example_content_array');
  return $content;
}

/**
 * An example page where the output is supplied as an array which
 * is themed into a list and styled with css.
 *
 * In this case we'll use the core-provided theme_item_list as a #theme_wrapper.
 * Any theme need only override theme_item_list to change the behavior.
 */
function theming_example_list_page() {
  $items = array(
    t('First item'),
    t('Second item'),
    t('Third item'),
    t('Fourth item'),
  );

  // First we'll create a render array that simply uses theme_item_list.
  $title = t("A list returned to be rendered using theme('item_list')");
  $build['render_version'] = array(
    // We use #theme here instead of #theme_wrappers because theme_item_list()
    // is the classic type of theme function that does not just assume a
    // render array, but instead has its own properties (#type, #title, #items).
    '#theme' => 'item_list',
    // '#type' => 'ul',  // The default type is 'ul'
    // We can easily make sure that a css or js file is present using #attached.
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
    '#title' => $title,
    '#items' => $items,
    '#attributes' => array('class' => array('render-version-list'))
  );

  // Now we'll create a render array which uses our own list formatter,
  // theme('theming_example_list').
  $title = t("The same list rendered by theme('theming_example_list')");
  $build['our_theme_function'] = array(
    '#theme' => 'theming_example_list',
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')),
    '#title' => $title,
    '#items' => $items,
  );
  return $build;
}


/**
 * A simple form that displays a select box and submit button.
 *
 * This form will be be themed by the 'theming_example_select_form' theme
 * handler.
 */
function theming_example_select_form($form, &$form_state) {
  $options = array(
    'newest_first' => t('Newest first'),
    'newest_last' => t('Newest last'),
    'edited_first' => t('Edited first'),
    'edited_last' => t('Edited last'),
    'by_name' => t('By name'),
  );
  $form['choice'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#title' => t('Choose which ordering you want'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Go'),
  );
  return $form;
}
function theming_example_select_form_submit($form, &$form_state) {
  drupal_set_message(t('You chose %input', array('%input' => $form_state['values']['choice'])));
}

/**
 * A simple form that displays a textfield and submit button.
 *
 * This form will be rendered by theme('form') (theme_form() by default)
 * because we do not provide a theme function for it here.
 */
function theming_example_text_form($form, &$form_state) {
  $form['text'] = array(
    '#type' => 'textfield',
    '#title' => t('Please input something!'),
    '#required' => TRUE,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Go'),
  );
  return $form;
}
function theming_example_text_form_submit($form, &$form_state) {
  drupal_set_message(t('You entered %input', array('%input' => $form_state['values']['text'])));
}


/**
 * Theme a simple content array.
 *
 * This theme function uses the newer recommended format where a single
 * render array is provided to the theme function.
 */
function theme_theming_example_content_array($variables) {
  $element = $variables['element'];
  $output = '';
  foreach (element_children($element) AS $count) {
    if (! $count) {
      // The first paragraph is bolded.
      $output .= '<p><strong>' . $element[$count] . '</strong></p>';
    }
    else {
      // Following paragraphs are just output as routine paragraphs.
      $output .= '<p>' . $element[$count] . '</p>';
    }
  }
  return $output;
}

/**
 * Theming a simple list.
 *
 * This is just a simple wrapper around theme('item_list') but it's worth
 * showing how a custom theme function can be implemented.
 *
 * @see theme_item_list()
 */
function theme_theming_example_list($variables) {
  $title = $variables['title'];
  $items = $variables['items'];

  // Add the title to the list theme and
  // state the list type. This defaults to 'ul'.
  // Add a css class so that you can modify the list styling.
  // We'll just call theme('item_list') to render.

  $variables = array(
    'items' => $items,
    'title' => $title,
    'type' => 'ol',
    'attributes' => array('class' => 'theming-example-list'),
  );
  $output = theme('item_list', $variables);
  return $output;
}

/**
 * Theming a simple form.
 *
 * Since our form is named theming_example_select_form(), the default
 * #theme function applied to is will be 'theming_example_select_form'
 * if it exists. The form could also have specified a different
 * #theme.
 *
 * Here we collect the title, theme it manually and
 * empty the form title. We also wrap the form in a div.
 */
function theme_theming_example_select_form($variables) {
  $form = $variables['form'];
  $title = $form['choice']['#title'];
  $form['choice']['#title'] = '';
  $output = '<strong>' . $title . '</strong>';
  $form['choice']['#prefix'] = '<div class="container-inline">';
  $form['submit']['#suffix'] = '</div>';
  $output .= drupal_render_children($form);
  return $output;
}

/**
 * Implements template_preprocess() to add information to the
 * theming_example_text_form().
 *
 * In this example the form is preprocessed here and $text_form
 * ($variables['text_form]) is ready to be output as prepared here when we get
 * to theming_example_text_form.tpl.php. However, other variables are provided
 * for use there; every key of the $variables array will be available as a
 * variable in the template.
 */
function template_preprocess_theming_example_text_form(&$variables) {
  $variables['text_form_content'] = array();
  $text_form_hidden = array();
  // Provide variables named after form keys so theme can output each element independently.
  foreach (element_children($variables['form']) as $key) {
    $type = $variables['form'][$key]['#type'];
    if ($type == 'hidden' || $type == 'token') {
      $text_form_hidden[] = drupal_render($variables['form'][$key]);
    }
    else {
      $variables['text_form_content'][$key] = drupal_render($variables['form'][$key]);
    }
  }
  // Hidden form elements have no value in the theme. No need for separation.
  $variables['text_form_content']['hidden'] = implode($text_form_hidden);
  // Collect all form elements to make it easier to print the whole form.
  $variables['text_form'] = implode($variables['text_form_content']);
}