guus van de wal
Menu

Theme wrappers in Drupal forms

8 March 2023

Update: looking for Drupal 8 guidance? I wrote a follow up for D8. 🙌

Ever tried to style Drupal forms? It's hard (at first). This is a blog item about form alters and theme wrappers for Drupal7 forms.

Let's say you have made a webform with Drupal and now you'd have to style it to match certain HTML (such as a framework as bootstrap or foundation or perhaps a custom framework)

First, you'll have to write a module to override Drupal's webform default behaviour. I'm assuming you already know how to. In that module you' ll need to declare a hook_form_id_alter, for instance, to add a class to the form tag:

Code Syntax Block php

/**
 * Implements HOOK_form_FORM_ID_alter
 */
function YOURMODULE_form_webform_client_form_alter(&$form, &$form_state, $form_id) {
  $form['#attributes']['class'][] = 'placeholder-form';
}

Drupal theme functions

All webforms are now being overridden with any code we'll supply. Let's assume you want to override the submit button. Perhaps you would like to change the default input element with a button element (since it's easier to style with :before and :after pseudo elements).  To accomplish that you'd have to write a theme function and let Drupal know that you'd like to use that (theme) function.

It then overrides the default theme_button function that can be found in form.inc from Drupal core. (somewhere around line 3858)

Code Syntax Block php

/**
 * Implements hook_theme().
 */
function YOURMODULE_theme() {
  return array(
    'YOURMODULE_submitbtn' =>  array('render element' => 'element'),
  );
}

function theme_YOURMODULE_submitbtn($variables) {
  $element                           = $variables['element'];
  $element['#attributes']['type']    = 'submit';
  element_set_attributes($element, array('id', 'name', 'value'));

  $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
  $element['#attributes']['class'][] = 'btn';
  if (!empty($element['#attributes']['disabled'])) {
    $element['#attributes']['class'][] = 'form-button-disabled';
  }
  return '<button' . drupal_attributes($element['#attributes']) . '> ' . $element['#value'] . ' </button>';
}

Last thing to do is to let know Drupal's webform that you would like to override it's theme wrappers:

Code Syntax Block php

/**
 * Implements HOOK_form_FORM_ID_alter
 */
function YOURMODULE_form_webform_client_form_alter(&$form, &$form_state, $form_id) {
  $form['actions']['submit']['#theme_wrappers'] = array('YOURMODULE_submitbtn');
}
So, all code together would look like this:

Code Syntax Block php

/**
 * Implements hook_theme().
 */
function YOURMODULE_theme() {
  return array(
    'YOURMODULE_submitbtn' =>  array('render element' => 'element'),
  );
}

function theme_YOURMODULE_submitbtn($variables) {
  $element                           = $variables['element'];
  $element['#attributes']['type']    = 'submit';
  element_set_attributes($element, array('id', 'name', 'value'));

  $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
  $element['#attributes']['class'][] = 'btn';
  if (!empty($element['#attributes']['disabled'])) {
    $element['#attributes']['class'][] = 'form-button-disabled';
  }
  return '<button' . drupal_attributes($element['#attributes']) . '> ' . $element['#value'] . ' </button>';
}

/**
 * Implements HOOK_form_FORM_ID_alter
 */
function YOURMODULE_form_webform_client_form_alter(&$form, &$form_state, $form_id) {
  $form['actions']['submit']['#theme_wrappers'] = array('YOURMODULE_submitbtn');
}

Happy theming! 😀

Update: looking for Drupal 8 guidance? I wrote a follow up for D8.