I don't post nearly enough of these, but here's one of my various Drupal 6 "Application Tricks".

Setup:
- i have a node type which is used to add a "Resource". A resource can be either a web link (link field) or an uploaded document (file field).
- i have a tab on the Resource form which houses the Creative Commons licensing subform as well as various other fields which are related ONLY to an upload file. Some of these fields (checkbox signoffs, see screen: http://screencast.com/t/5FgD8NEVLtf0) are set in CCK as REQUIRED.

Task:
- i only want these required fields to validate if i am uploading a file (not if it is just a web link resource)

Solution:

NOTE: mymodule must have a high system weight such that other modules have run their validate scripts already

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == "resource_node_form") {
    $form['#validate'][] = '_mymodule_resource_file_upload_validate';
  }
}

function _mymodule_resource_file_upload_validate($form, &$form_state) { 
  $upload = false;
  foreach ($form['#post']['field_file'] as $file) {
    if ($file['fid']) $upload = true;
  }
  
  // if we are uploading a file then we DO want our required fields
  // so just return and let Drupal do its thing
  if ($upload) return;
  
  // the required fields that we want to ignore since this isn't a file upload resource
  $safe_fields = array('field_agree', 'field_license_ack');
  
  // get a list of all errors
  $errors = form_get_errors();
  
  // clear all errors so we can add all of them back except the ones we are trying to clear
  form_set_error(null, null, true);
  if (count($errors)) {
    foreach ($errors as $field => $msg) {
      if (!in_array($field, $safe_fields)) form_set_error($field, $msg); 
    }
  }
  
  // need to do similar thing with Error messages since they have already been set as well
  $messages = drupal_get_messages('error');     // this will clear Error msg queue
  if (count($messages)) {
    foreach ($messages['error'] as $msg) {
      if (stristr($msg, "Contributor's Agreement") || stristr($msg, "License Acknowledge")) continue;
      drupal_set_message($msg, 'error'); 
    }
  }
  
}

Peter Lindstrom
LiquidCMS - Content Solution Experts

Comments

ferrum’s picture

As form_set_error() also sets the error messages again, the easier version is:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == "resource_node_form") {
    $form['#validate'][] = '_mymodule_resource_file_upload_validate';
  }
}

function _mymodule_resource_file_upload_validate($form, &$form_state) {
  $upload = false;
  foreach ($form['#post']['field_file'] as $file) {
    if ($file['fid']) $upload = true;
  }
 
  // if we are uploading a file then we DO want our required fields
  // so just return and let Drupal do its thing
  if ($upload) return;
 
  // the required fields that we want to ignore since this isn't a file upload resource
  $safe_fields = array('field_agree', 'field_license_ack');
 
  // get a list of all errors
  $errors = form_get_errors();
 
  $messages = drupal_get_messages('error');     // this will clear Error msg queue

  // clear all errors so we can add all of them back except the ones we are trying to clear
  form_set_error(null, null, true);
  if (count($errors)) {
    foreach ($errors as $field => $msg) {
      if (!in_array($field, $safe_fields)) form_set_error($field, $msg);
    }
  }
}
texas-bronius’s picture

The solutions above are Drupal 6. They were really close in Drupal 7, but form_set_error() didn't reset the error messages stack: I had inserted a drupal_set_message($key) in there just for debugging and had confirmed that it was executing as expected, and the fields did receive the Drupal FAPI field error css class, only the messages are not output to screen.

My use case: Have a radio selector Application Type of "single" or "joint" for credit application type, and when "single" is selected, I need to skip over field validation on the "Secondary Applicant" fields. Once I have that working, I am still a bit dubious how this might translate to toggling Application Type radios between form submissions, but first thing is first..

The difference was that I am working in Drupal 7. Read on!

Drupal 7 form_set_error() does away with Drupal 6 form_set_error()'s $reset flag, replacing it instead with $limit_validation_errors. That makes these awesome code snippets not work in D7. How to clear the form error stack now?

Drupal 7 introduces form_clear_error() to clear the FAPI form error stack instead of the now removed $reset third param to Drupal 6's form_set_error().

And so now both concerns mentioned earlier are gone by using the 2nd code snippet and replacing:

  // clear all errors so we can add all of them back except the ones we are trying to clear
  form_set_error(null, null, true);

with

  // clear all errors so we can add all of them back except the ones we are trying to clear
  form_clear_error(); // New with Drupal 7

--
http://drupaltees.com
80s themed Drupal T-Shirts

texas-bronius’s picture

Ah, I understand now why the @ferrum's shorter version works: when you clear both the form error and the messages error queues, our custom/intentional form_set_error within the foreach will be adding back any error notifications to the messages stack, making the drupal_set_message bit unnecessary/redundant. Kudos!

--
http://drupaltees.com
80s themed Drupal T-Shirts

WorldFallz’s picture

Also checkout the http://drupal.org/project/conditional_fields module -- works great.

_
Care about the future of the Drupal.org forums? Please join our conversation and show support for improving the forums infrastructure.

frederickjh’s picture

Sorry Conditional Fields only does in browser validation. When it comes time to submit the form it goes with what is set on the field.

So if you want to only require a second field when a checkbox is checked you can never get the validation you want.

If the check box is unchecked and the second field required by default even if conditional fields sets the java script state to unrequired on the second field upon submit you will get an error message that the second field is required.

If you try the same thing with the second field not required. The checkbox can be checked and no input given in the second field which the module will have set the javascript state to required (red asterisk),but on submit no error message will be given and it will be allowed to save even though the second field is empty.

The field_conditional_state module has less users and supports more fields but also fails to deliver the good too. Same story as above.

Just trying to save someone some time.

WorldFallz’s picture

So if you want to only require a second field when a checkbox is checked you can never get the validation you want.

You actually can. It's a little counter intuitive. Don't set the potentially required field as "required" in the field settings. Instead, add a second conditional_fields dependency that the field is "required" when the dependent is shown. If you've done it correctly, you'll see 2 conditions on the field joined with "and" on the dependency tab. So it will be "visible" AND "required" when the dependent has the desired value.

_
Care about the future of the Drupal.org forums? Please join our conversation and show support for improving the forums infrastructure.