The attached patch allows to disable one or more items in a group of checkboxes or radios. You just need to enter the #disabled as array and not as boolean value, like this:

$options = array('1' => 'First item', '2' => 'Second item', '3' => 'Third item', '4' => 'Fourth item');
$disabled = array(2, 3);
$form['checkboxes'] = array('#type' => 'checkboxes', '#options' => $options, '#disabled' => $disabled);

In this example the checkboxes with keys 2 and 3 will be disabled. The #disabled array must contain the keys of the items that must be disabled. When #disabled is boolean, it works as usual and all items will be disabled.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ximo’s picture

+1 for this patch, I think the Forms API should include this

ximo’s picture

Could the Forms API for checkboxes and radios be rewritten to support the following code?

<?php
$form['foobar'] = array(
  '#type' => 'checkboxes',
  '#title' => t('Some checkboxes'),
  '#options' => array(
    'foo' => array(
      // will default to '#type' => 'checkbox' in this case,
      '#title' => t('This checkbox is disabled and checked by default'),
      '#default_value' => TRUE,
      '#disabled' => TRUE,
    ),
    'bar' => t('This checkbox is plain and simple'),
  ),
);
?>

In other words, have Forms API support the #checkbox/#radio type for every checkbox/radio option, giving each option the same properties as a stand-alone checkbox/radio. This would allow for more advanced forms, and would make this suggestion easy to implement. However it looks like a lot of rewrite, and unfortunately I don't know form.inc enough to implement this myself (yet).

ximo’s picture

Here's a an updated version of stafano73's patch for revision 1.177..

shunting’s picture

Until the forms API does include it, you can set the #attributes property of the individual form element (button, box, etc) to something like array('disabled'=>'disabled') if you want.

See

http://api.drupal.org/api/HEAD/file/developer/topics/forms_api_reference...

Less than elegant but it does work.

tonyn’s picture

+1, looking forward to this.

Junyor’s picture

Status: Active » Needs review

It would be good to be able to disable individual options in a SELECT element, too.

scafmac’s picture

Is a patch really needed? You can control individual radio buttons with the 5.x forms api - http://drupal.org/node/68740#comment-268897 - you just cannot use the '#options' item...

Junyor’s picture

Title: Disable specific checkbox or radio items » Disable specific checkbox, radio, option, or optgroup items

Your approach is rather difficult and hidden compared to just having #options. This should apply to radio buttons, check boxes, options, and optgroups.

chx’s picture

Version: 6.x-dev » 7.x-dev
Status: Needs review » Needs work

Patch needs reroll and despite this is a cool feature, we are not adding new features, small or big to core now.

Pancho’s picture

FileSize
1.51 KB

Here's a rerolled patch against HEAD (which is now 7.x-dev). Please test.

Pancho’s picture

Status: Needs work » Needs review

Remark: This one here is blocking #119038

kenorb’s picture

For disabling specified checkbox you can use followed function in form_alter hook:

/*
 * Change options for individual checkbox or radio field in the form
 * You can use this function using form_alter hook.
 * i.e. _set_checkbox_option('field_tier_level', 'associate', array('#disabled' => 'disabled'), $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $checkbox_name (string)
 *    Name of checkbox to change options (if it's null, set to all)
 * @param $options (array)
 *    Custom options to set
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _set_checkbox_option($field_name, $checkbox_name = NULL, $options, &$form) {
    if (isset($form[$field_name]) && is_array($form[$field_name])) {
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                $type = $form[$field_name][$key]['#type'];
                break;
            }
        }
        if (isset($curr_arr) && is_array($curr_arr['#default_value'])) {
            switch ($type) { // changed type from plural to singular
                case 'radios':
                    $type = 'radio';
                    break;
                case 'checkboxes':
                    $type = 'checkbox';
                    break;
            }

            foreach ($curr_arr['#default_value'] as $key => $value) {
                foreach($curr_arr as $old_key => $old_value) { // copy existing options for to current option
                    $new_options[$old_key] = $old_value;
                }
                $new_options['#type'] = $type;  // set type
                $new_options['#title'] = $value;  // set correct title of option
                $curr_arr[$key] = $new_options; // set new options

                if (empty($checkbox_name) || strcasecmp($checkbox_name, $value) == 0) { // check name or set for 
                    foreach($options as $new_key => $new_value) {
                        $curr_arr[$key][$new_key] = $value;
                    }
                }
            }
            unset($curr_arr['#options']); // delete old options settings
        } else {
            return NULL;
        }
    } else {
        return NULL;
    }
}

Or for disabling field this one:

/*
 * Disable selected field in the form(whatever if it's textfield, checkbox or radio)
 * You can use this function using form_alter hook.
 * i.e. _disable_field('title', $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _disable_field($field_name, &$form) {
    $keyname = '#disabled';

    if (!isset($form[$field_name])) { // case: if field doesn't exists, put keyname in the main array
        $form[$keyname] = TRUE;
    } else if (!isset($form[$field_name]['#type']) && is_array($form[$field_name])) { // case: if type not exist, find type from inside of array
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                break;
            }
        }
    } else {
        $curr_arr = &$form[$field_name]; // set field array as current
    }

    // set the value
    if (isset($curr_arr['#type'])) {
        switch ($curr_arr['#type']) {
            case 'textfield':
            default:
                $curr_arr[$keyname] = TRUE;
        }
    }
}
lilou’s picture

Category: task » feature
Status: Needs review » Needs work

Patch no longer applied.

jeffschuler’s picture

Status: Needs work » Needs review
FileSize
1.07 KB

+1 for this functionality.

Re-rolled Pancho's #10 to apply to HEAD.

catch’s picture

This looks good - seems like we could use it for the forum select to exclude containers? That'd make it easy to write a test for this as well.

Status: Needs review » Needs work

The last submitted patch failed testing.

jeffschuler’s picture

Status: Needs work » Needs review
FileSize
1.19 KB

Re-rolled again for current HEAD, and resolved an issue that testbot was choking on.

@catch, I'm not very familiar... If you could please give me more info on use "for the forum select to exclude containers", I'll see what I can do.

Status: Needs review » Needs work

The last submitted patch failed testing.

jeffschuler’s picture

Status: Needs work » Needs review
FileSize
1.2 KB

Missed the change from $form to $element in _form_builder_handle_input_element().

Re-test of form.inc_104715_disableCheckboxes_4.patch from comment #19 was requested by Arancaytar.

catch’s picture

Would be good if this could be re-rolled with -up to get function names for context.

Also we should apply this to forum containers to remove some horribly validation code.

cburschka’s picture

Here's the -up.

TomSherlock’s picture

Forgive my ignorance; i'm not familiar with the proper way to construct patches.

Is this a typo:

@@ -2290,6 +2295,11 @@ function form_process_checkboxes($elemen

Should that be element?

effulgentsia’s picture

Status: Needs review » Closed (duplicate)

Seems same / very similar to #284917: Allow FAPI select, radios, and checkboxes to specify some options as disabled, so let's join forces over there. Marking this one as the duplicate rather than that one, because I prefer the use of a new property #disabled_options as is done on that issue rather than overloading #disabled.