3

In the current Drupal configuration required fields simply display an asterisk wrapped in span of class "form-required":

return '<span' . drupal_attributes($attributes) . '>*</span>

This isn't really suitable and I have noticed quite a few users miss the asterisk (poor visibility, etc.). To combat this I would like to apply much better styling / hinting to all elements of a required field (label, value, background, etc.).

How do I add a span wrapper to al required fields on the form?

<span class="form-field-required">
  <label for="some-field">Label</label>
  <div id="some-field">
  ....
  </div>
</span>

I presume I need to use hook_form_alter() but not sure what I need to check or how to output the original field data correctly/safely.

  • 1
    You know that's invalid HTML, right? – Clive Oct 25 '13 at 15:07
  • 1
    Agreed with @Clive, however it can be easily changed to a <div>. The way to do it with hook_form_alter is to check the element's #required property and set '#prefix' => '<div class="form-field-required">' and '#suffix' => '</div>' – Beebee Oct 25 '13 at 15:13
2

I'd suggest you create an implementation of the theme hook form_element, to add a new class at the top level rather than an extra div which is simply redundant. That way you don't have to recursively process every form on the site looking for required fields. Unfortunately the standard form_element implementation is not designed in a very helpful way, so you have to duplicate a lot of code:

  function mymoduleortheme_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');
    // extra code here --->
    if(!empty($element['#required'])) {
      $attributes['class'][] = 'form-element-required';
    }
    // <---
    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>' : '';

    switch ($element['#title_display']) {
      case 'before':
      case 'invisible':
        $output .= ' ' . theme('form_element_label', $variables);
        $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 .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
        break;
    }

    if (!empty($element['#description'])) {
      $output .= '<div class="description">' . $element['#description'] . "</div>\n";
    }

    $output .= "</div>\n";

    return $output;
  }

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.