Tell me more ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

Is there a way in Drupal 7 to change the location of the output of form_set_error?

At the moment, it calls drupal_set_message which queues all the form's errors to the top of the screen.

What I would like instead is for each message to appear below the appropriate field.

If this is not possible, can I manually flag the form as "invalid" within the MODULE_form_name_validate() function without using form_set_error?

share|improve this question

2 Answers

up vote 5 down vote accepted

The Inline Form Errors module has that functionality:

IFE or Inline Form Errors allows you to place form submission error inline with the form elements. Three options are provided for setting your inline error behaviour. You can configure the default behaviour or override the behaviour on a per form basis. You can add as many forms as you like.

The Drupal 7 release is only in alpha but I'd say it's worth a try. Even if there are issues, it should give you a good place to start to implement your own version. This is the module screenshot:

enter image description here

share|improve this answer

Extending the (correct) answer from Clive, I worked through the IFE code. I didn't really need an entire module dedicated to this, so I adopted a few snippets here and there to get the result I needed. I've marked his answer as correct because it is ultimately the right answer.

The code is below, all credit goes to Clive and the IFE team - I just wanted to present the simplified version for anyone looking for a similar answer.

// Standard gear - do some custom validation and set the errors
// as you go..
// 
// Once all the validation has been done, call MODULE_errors_reset
// which will return an array of all errors against their ID. 
// Expose this array however you like to your template, or loop
// over your form adding a #suffix to each element with an error
//
function MODULE_form_name_validate($form, &$form_state) {
    drupal_set_message("validating...");

    form_set_error("description", "There is an error here!!!!");
    form_set_error("tags", "Yep, and here too!!!");

    $reset_errors = MODULE_errors_reset( $form );

    drupal_set_message( "<pre>" . print_r( $reset_errors, true ) . "</pre>" );
}

// This part is adopted from IFE. It's changed in two ways, it returns
// an array (which also merges with its recursive self). 
// And it also skips all the 'display' stuff present in the original
// Essentially it extracts out the error messages from the session and unsets 
// them. I am assuming that Drupal 7 marks the success of a validation based not
// whether the SESSION variable contains anything, the SESSION seems to be only
// for the message at the top of the screen.
//
function MODULE_errors_reset( $element ) {
    if( ! isset( $_SESSION[ 'messages' ] ) ) {
        return;
    }

    $reset_errors = array();

    // Recurse through all children.
    foreach( element_children( $element ) as $key ) {
        if( isset( $element[ $key ] ) && $element[ $key ] ) {
            $reset_errors += MODULE_errors_reset( $element[ $key ] );
        }
    }

    // Check for errors and settings
    $errors = form_get_errors();
    $element_id = implode( '][', $element[ '#parents' ] );

    if ( !empty( $errors[ $element_id ] )) {
        $error_message = $errors[ $element_id ];

        // Get error id
        $error_id = array_search( $error_message, $_SESSION[ 'messages' ][ 'error' ] );

        if( $error_id !== FALSE ) {
            unset( $_SESSION[ 'messages' ][ 'error' ][ $error_id ] );
            $_SESSION[ 'messages' ][ 'error' ] = array_values( $_SESSION[ 'messages' ][ 'error' ]  );

            if( count( $_SESSION[ 'messages' ][ 'error' ] ) <= 0 ) {
                unset( $_SESSION[ 'messages' ][ 'error' ] );
            }

            $reset_errors[ $element[ '#id' ] ] = $error_message;
        }
    }

    return $reset_errors;
}

// If there are no form errors, we still hit here, even after the 'reset', this is
// a good thing. 
function MODULE_form_name_submit( $form, &$form_submit ) {
    drupal_set_message("submited!");
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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