Here is a little extension that would allow conditional required fields to have custom validation done on them. Most my patches seem to fail to parse, so I'll paste it here:

<?php
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.327
diff -u -r1.327 form.inc
--- includes/form.inc	11 Apr 2009 22:19:44 -0000	1.327
+++ includes/form.inc	19 Apr 2009 15:43:18 -0000
@@ -780,10 +780,18 @@
       // A simple call to empty() will not cut it here as some fields, like
       // checkboxes, can return a valid value of '0'. Instead, check the
       // length if it's a string, and the item count if it's an array.
-      if ($elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0))) {
-        form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+      if ($elements['#required'] || isset($elements['#required_validate'])) {
+        if (isset($elements['#required_validate'])) {
+          foreach ($elements['#required_validate'] as $function) {
+            if (function_exists($function))  {
+              $function($elements, $form_state, $complete_form);
+            }
+          }
+        }
+        elseif (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0)) {
+          form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+        }
       }
-
       // Verify that the value is not longer than #maxlength.
       if (isset($elements['#maxlength']) && drupal_strlen($elements['#value']) > $elements['#maxlength']) {
         form_error($elements, $t('!name cannot be longer than %max characters but is currently %length characters long.', array('!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'], '%max' => $elements['#maxlength'], '%length' => drupal_strlen($elements['#value']))));

?>

The usage is as follows:

<?php
// Form element
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Preset name'),
    '#default_value' => $edit['name'],
    '#maxlength' => 215,
    '#required' => TRUE,
    '#required_validate' => array('crc_test'),
  );

// The callback
function crc_test($elements, $form_state, $complete_form) {
  if (empty($elements['#value']) && !empty($form_state['values']['another field'])) {
    form_error($elements, t('!name field is required.', array('!name' => $elements['#title'])));
  }
}
?>

Use case, a number of different options on a form and other fields are dependent on the values of these. Using the above patch, we can flag all fields are required, but only trigger an error if missing the correct combination of values. This is fairly common with javascript based toggles.

CommentFileSizeAuthor
#3 form.validation.3.patch1.86 KBAlan D.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

Status: Needs review » Active

There is no patch so this hardly can be CNR. Your patch would be quite fine by the way. I cant see the use for this, however -- why you cant simply use #process to copy the #value around if necessary?

Alan D.’s picture

I can not understand how you would do this using the #process callback to trick the theme layer that the element is required and to stop the validation at the logic layer. Could you expand on this idea? Thanks.

The simplest example would be a select list with an "Other, please specify" option & matching textfield.

A simple JScript toggle can be used to hide or show the textfield, but there is no simple way to highlight the textfield as required when the "Other, please specify" option is selected. On a custom install, this can be done with JScript, but not on a generic site as the HTML for the required flag could have custom theming applied.

Regarding the patch, or lack of, I've set Eclipse up to use all of the standard CVS preferences for drupal.org, but not a single patch has passed the Bot in the last 6 months+. So I've given up on posting patches.

Alan D.’s picture

Status: Active » Needs review
FileSize
1.86 KB

@chx Is it possible to get an 30sec overview of how you would use #process to trick the system into thinking that the element is required without actually validating it. Many thanks. I've read over the code a few times and can not figure out how this is possible.

I am finding many use cases now I'm thinking of this issue. For example, in a multistep form with prev & next submit handlers, when the fields are marked as required, you get errors trying to go back a step. Another use case is a cancel button (or another similar action), and a submit. Having standard required fields result in validation errors on the cancel action.

sun’s picture

This mixes two completely separate issues:

1) (Just) Marking fields as required, without requiring them to be non-empty.

2) Conditionally using optional validation handlers for fields.

3) Making multi-step forms as well as form buttons executing non-default actions work with unrelated, required fields in the form.

--

3) shouldn't be discussed here.

2) Is a valid use-case, but we want to look at this in a broader scope, and I believe that there is at least one other issue with regard to more flexible validation.

1) If you think about it, it doesn't make sense to mark a non-required field as required from a usability perspective. The only use-case that I know of is if you have a group of form items (i.e. a 'multiple' field containing multiple other fields), which are - as group - optional, but only if the user wants to fill out (add) the group of fields, one or more of the fields may be required.

Alan D.’s picture

Hi Sun

Thanks for the feedback.

#1 This is where I first started thinking that there must be an alternative and could not find one. I know that I've been surprised a couple times on Drupal sites when the required flag is missing (always due to custom validation on a split workflow within a form). In core there is a save / delete that also suffers from this issue, but I can not remember where at the moment.

#2 I'm do a search and look into it. Happy to mark this as a duplicate if these other solutions help. This is primarily focused on being able to interact with the theming of the required field, the only element outside of the elements direct control. Maybe a theming call for this chunk of HTML to allow elements to insert the required HTML themselves and to keep the markup consistent with the rest of the system.

I hit #3 in a custom shopping cart system, where having a Modify button (Eg: Modify the cart) on the checkout screen where user enters their details. This was the clients design, not ours. Workaround, changing this button to a image link (returns to another form so easily bypassed).

Status: Needs review » Needs work

The last submitted patch failed testing.

sun.core’s picture

Version: 7.x-dev » 8.x-dev
Cyberwolf’s picture

Subscribing.

Bodo Maass’s picture

Subscribing.

My use case is related the cancel action described by Alan in #3. I want a special button that allows users to save an incomplete form so that they can return to it later. The normal submit button should have full validation, but the cancel+save button should allow required fields to be empty. I think the logic described here would allow something like this, while the forms api out of the box does not.

Alan D.’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Closed (works as designed)

Very simple workaround that works in D7 and probably D6 (Don't overwrite any existing #pre_renders!!)

This works by tricking the theme layer that the element is required

function hook_form_alter(&$form, &$form_state, $form_id) {
  $form['field_description']['und'][0]['#pre_render'][] = 'hook_mark_required';
  $form['field_description']['und'][0]['#element_validate'][] = 'hook_custom_required_validator';
}

function hook_mark_required($elements) {
  $elements['#required'] = TRUE;
  return $elements;
}
iMiksu’s picture

Version: 7.x-dev » 8.x-dev
Status: Closed (works as designed) » Active

I think this is still a valid request for example cases where developers wants the element to be required in certain conditions.

Good use case would be that certain elements are required if some checkbox is checked (eq. radio "Other, write below"). After moments, I still haven't figure it out how to implement this.

Only thing I came up with was that I actually determine a callback function as string instead a TRUE/FALSE for $element['#required'] element.

// Usage example
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  // ...
  $form['my_textfield']['#required'] == 'mymodule_is_required';
}

/**
 * Callback for telling FAPI whether the element is required or not.
 */
function mymodule_is_required($element, &$form, &$form_state) {
  return (bool) $form_state['values']['my_checkbox']['value'];
}

When running _form_validate() it could check the $elements['#required'] variable type whether it's a boolean or string. If it's a string, try to call the function.

iMiksu’s picture

Status: Active » Closed (works as designed)

Sorry for last post. Like always, the solutions are always found suddenly just after writing something to the issue queue :D

I found #element_validate :)