2

I have a form with input fields such as this one:

'sex' => array(
    '#type' => 'radios',
    '#title' => t('Sex'),
    '#options' => array('m' => t('M'), 'f' => t('F')),
    '#description' => t("We use this to write Mr. or Mrs. in the letters we send you.")
)

By default, this prints the label first ('Sex'), then the radio buttons, and then the description. I would like to print out the label followed immediately by the description and have the radio buttons appear last. How can I achieve this? I know how to load a stylesheet, but in this case it would be nice for the html to appear in the correct order: <label /><div class="description" /><input /> rather than <label /><input /><div class="description" />

Edit: The solution proposed by Anil Sagar works, but introduces a bug. Indeed, what I use his solution, it prevents me from giving a description to a checkbox field. In other words, if I write

$form['myCheckbox'] = array(
  '#type' => 'checkbox',
  '#title' => t('My checkbox'),
  '#description' => t("My description")
);

that description never makes it to the HTML. Does anyone know how to fix this?

4 Answers 4

1

You need to override theme_form_element in your theme template.php to change the order of the form field description. See below code which will change order for all fields.

If you would like to change for only one field, then add a if condition by inspecting $element array only for your field !

function yourtheme_form_element($variables) {
  $element = &$variables['element'];
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  // This function is invoked as theme wrapper, but the rendered form element
  // may not necessarily have been processed by form_builder().
  $element += array(
    '#title_display' => 'before',
  );

  // Add element #id for #type 'item'.
  if (isset($element['#markup']) && !empty($element['#id'])) {
    $attributes['id'] = $element['#id'];
  }
  // Add element's #type and #name as class to aid with JS/CSS selectors.
  $attributes['class'] = array('form-item');
  if (!empty($element['#type'])) {
    $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
  }
  if (!empty($element['#name'])) {
    $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
  }
  // Add a class for disabled elements to facilitate cross-browser styling.
  if (!empty($element['#attributes']['disabled'])) {
    $attributes['class'][] = 'form-disabled';
  }
  $output = '<div' . drupal_attributes($attributes) . '>' . "\n";

  // If #title is not set, we don't display any label or required marker.
  if (!isset($element['#title'])) {
    $element['#title_display'] = 'none';
  }
  $prefix = isset($element['#field_prefix']) ? '<span class="field-prefix">' . $element['#field_prefix'] . '</span> ' : '';
  $suffix = isset($element['#field_suffix']) ? ' <span class="field-suffix">' . $element['#field_suffix'] . '</span>' : '';
   $element_description = "";
  if (!empty($element['#description'])) {
    $element_description = '<div class="description">' . $element['#description'] . "</div>\n";
  }
  switch ($element['#title_display']) {
    case 'before':
    case 'invisible':
      $output .= ' ' . theme('form_element_label', $variables);
      $output .= $element_description;
      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
      break;

    case 'after':
      $output .= ' ' . $prefix . $element['#children'] . $suffix;
      $output .= ' ' . theme('form_element_label', $variables) . "\n";

      break;

    case 'none':
    case 'attribute':
      // Output no label and no required marker, only the children.
      $output .= $element_description;
      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
      break;
  }
  $output .= "</div>\n";

  return $output;
}

Other way & simple way to solve this problem is use jQuery to change the position. This will help you !

4
  • Apparently, this method (overriding theme_form_element) has a nasty side effect. I can no longer add a description on a checkbox ($form['a'] = array('#type'=>'checkbox','#description'=>'hello');: The description never makes it to the html).
    – Shawn
    Oct 16, 2012 at 21:22
  • Is anyone able to reproduce the problem mentionned in my previous comment?
    – Shawn
    Oct 19, 2012 at 17:31
  • Ok, I figured it out. The problem is avoided by adding $output .= $element_description; at the end of case 'after':
    – Shawn
    Oct 22, 2012 at 15:31
  • There is another problem with this code, detailed here: drupal.stackexchange.com/questions/48918/…
    – Shawn
    Oct 26, 2012 at 18:40
0

You can solve this with the label_help module, which is made specifically for this purpose.

In the field settings, it will introduce one more field called "Label help message", which is "Help text to insert below the label and above the input form element." This way, you can choose for each field if you want a description above the field, below it, or both.

0

Better Field Descriptions is another useful module-- although it doesn't help with user registration forms. https://www.drupal.org/project/better_field_descriptions

-1

I found this very helpful blog post to fix this problem : http://www.whenwhowhere.com/tech-blog/move-description-field-below-label-drupal-7-form

Basically, in hook_form_alter, you put the title and the description in the #prefix of the element, then unset the title and the description so they don't appear twice ... I tried it and it works perfectly.

2
  • And all modules that expect title and description to be there, and try to use them in their form alters, will start to fail. This can and should be done at theme level, not the way you are posting here.
    – Mołot
    Nov 20, 2014 at 21:21
  • Ok then just hide the title and description with css then ...
    – agodin
    Nov 20, 2014 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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