Currently Form API only displayed error messages at the top of the page with each field that has an error would be highlighted in red. Most of the form library has this feature so it would be pity FAPI doesn't has it. For now I plan to just hack up _form_set_class() function since this is the one that is called by all the element prior to rendering.

function _form_set_class(&$element, $class = array()) {                            
  if ($element['#required']) {                                                     
    $class[] = 'required';                                                         
  }                                                                                
  if (form_get_error($element)){                                                   
    $class[] = 'error';                                                            
    $element['#title'] = '<span style="color: red;">'.form_get_error($element).'</span><br />'.$element['#title'];
  }
  if (isset($element['#attributes']['class'])) {                                   
    $class[] = $element['#attributes']['class'];                                   
  } 
  $element['#attributes']['class'] = implode(' ', $class);                         
}

I used #title since there's no other property that can output some content before the element.

Comments

walker2238’s picture

Is there not a way to override this function? I'm kinda looking for something along the same lines as you. I have yet to find a way to override this and don't really like the idea of making a hack in the core files. The way drupal outputs status and error messages is driving me nuts. As you suggested putting the messages beside each field is a much more user friendly way.

k4ml’s picture

Turn out that we can override this in theme function though not really clean but I think much better. Found this at http://www.imedstudios.com/labs/node/4 and here is my version which display the error on top of the element instead of bottom:-

function garland_form_element($element, $value) {
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  $output = '<div class="form-item"';
  if (!empty($element['#id'])) {
    $output .= ' id="'. $element['#id'] .'-wrapper"';
  }
  $output .= ">\n";

  // Set error messages on top of each elements
  if ($error = form_get_error($element)) {
    $idx = array_search($error, $_SESSION['messages']['error']);
    if ($idx !== FALSE) {
      unset($_SESSION['messages']['error'][$idx]);
      $output .= "<div class = 'messages error'>$error</div>";
    }
    $idx = array_search('Please correct all highligted errors and try again.', $_SESSION['messages']['error']);
    if ($idx === FALSE) {
      drupal_set_message('Please correct all highligted errors and try again.', 'error');
    }
  }
  $messages = drupal_get_messages('error');
  if (empty($messages)) {
    unset($_SESSION['messages']['error']);
  }
  // End Set error messages on top of each elements

  $required = !empty($element['#required']) ? '<span class="form-required" title="'. $t('This field is required.') .'">*</span>' : '';

  if (!empty($element['#title'])) {
    $title = $element['#title'];
    if (!empty($element['#id'])) {
      $output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
    else {
      $output .= ' <label>'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
  }

  $output .= " $value\n";

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

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

  return $output;

}
dww’s picture

Status: Active » Closed (won't fix)

This isn't going to be fixed in D5 (or D6) for that matter. Looks like something like this might land in D7 over at #447816: WCAG violation: Relying on a color by itself to indicate a field validation error.