10

How do I disable an option in the select form field?

$form['feed'] = array(
  '#type' => 'select', 
  '#title' => t('Display of XML feed items'), 
  '#options' => array(
    'title' => t('Titles only'), 
    'teaser' => t('Titles plus teaser'), 
    'fulltext' => t('Full text'),
  ),
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

How can I disable, for example, the "Title only" option?

1
  • This would be great to know how to do, I still want the option to appear in the list, but not be selectable...
    – DrCord
    Sep 30, 2014 at 15:01

7 Answers 7

6

The only way to disable one of the options for a "select" form field is to override the theme_select() function implementing hook_theme_registry_alter().

theme_select() executes the following code:

function theme_select($variables) {
  $element = $variables['element'];
  element_set_attributes($element, array('id', 'name', 'size'));
  _form_set_class($element, array('form-select'));

  return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>';
}

The function that you implement should invoke your own function instead of form_select_options().

As theme_select() is called for each select field used in any Drupal form, I would rather consider implementing hook_form_alter() to remove the option from the form field you want.

6

Disabling an option may be tricky to achieve (Using form_alter to disable ONE option of a select field) so I'll recommend you to look at optgroups as an alternative. The Drupal form API documentation doesn't explain it but the API allows nested array for the options, have a look at form_select_options() and the <optgroup> part.
You can write this code:

$form['feed'] = array(
    '#type' => 'select', 
    '#title' => t('Display of XML feed items'), 
    '#options' => array(
        'Titles only' => array(, 
          'teaser' => t('Titles plus teaser'), 
          'fulltext' => t('Full text'),
        ),
        'Titles only 2' => array(, 
          'teaser2' => t('Titles plus teaser 2'), 
          'fulltext2' => t('Full text 2'),
        ),
    ),
    '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

Have a look at Drupal 6 forms and optgroup arrays.

Edit: to clarify this is an alternative and not a direct answer.

3
  • The question is about disabling one of the options, not grouping them.
    – apaderno
    Aug 26, 2011 at 20:06
  • I understood that but I thought optgroup provided a good alternative.
    – tostinni
    Aug 26, 2011 at 20:14
  • brilliant! That's exactly what I was looking for, thank you!!!
    – uwe
    Nov 11, 2011 at 3:14
4

I got mine working with the following line

unset($form['field_name']['und']['#options'][1]);

where 1 is the index of the item which you don't want to be displayed.

2
  • This removes the option. The question is about disabling the option (leaving it displayed grayed out).
    – Koen
    Nov 12, 2015 at 12:32
  • True @Koen - for me personally, this was a quick and easy alternative solution that I implemented instead of going down the "disable" route. It allowed me to stop a user selecting a specific option for an active form, while leaving the option within the setup for archived/past submissions. Jan 17, 2021 at 23:37
3

I don't know and haven't been able to find any way to disable an individual option. It does look like they are trying to get something like this into Drupal. Maybe some alternatives, could what you want be done with css?:

$form['feed']['#attributes'] = array('class' => array('options-styles-class'));

Or, if you don't want the values to be shown at all you can unset them

unset($form['feed']['#options']['title']);
1

Convert the one single item you want to disable into an empty <optgroup>.

Pros:

  • This can be done in a hook_form_alter or directly when building your custom form, there is no need to implement a theme_select function in your theme.

Cons:

  • There's no way to represent the value='title' attribute associated with the original <option> in the resulting DOM.
  • YMMV if you're trying to disable an option that already pertains to an optgroup. Nested optgroups might indeed work, but this is untested and unconfirmed.

Implementation:

Optgroups in Drupal are denoted inside the #options array as any key => value pairs where the value is itself an array.

So from the example in the OP we would move the value of t('Titles only') to become the key and then make the value be an empty array.

$form['feed'] = array(
  '#type' => 'select', 
  '#title' => t('Display of XML feed items'), 
  '#options' => array(
    t('Titles only') => array(), // This one becomes disabled as an empty optgroup
    'teaser' => t('Titles plus teaser'), 
    'fulltext' => t('Full text'),
  ),
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

The resulting HTML will look something like this:

<form>
  <div>
    <label>Display of XML feed items</label>
    <select>
      <optgroup>Titles only</optgroup>
      <option value="teaser">Titles plus teaser</option>
      <option value="fulltext">Full text</option>
    </select>
  </div>
</form>
0

For disabling the whole field, use

$form['field_name']['#disabled']= TRUE;

For disabling an option in the select field, use

unset($form['field_name']['und']['#options'][1]);

where:

['field_name'] is the name of the your field

[1] is the index of the option in the list

0

For drupal 8 or 9 you could take a look to the anwser on this page https://drupal.stackexchange.com/a/207505/89554.

You have to install the module https://www.drupal.org/project/form_options_attributes

Usage

To add attributes to a form element's options, add an #options_attributes key to the form element definition. The #options_attributes value should be an array with keys that match the keys in the #options value array. The values in the #options_attributes array should be formatted like the main #attributes array

Exemple based on the question

Set the form field like this:

$form['states'] = [
  '#type' => 'select',
  '#title' => t('Display of XML feed items'),
  '#options' => [
    'title' => t('Titles only'),
    'teaser' => t('Titles plus teaser'),
    'fulltext' => t('Full text'),
  ],
  '#options_attributes' => [
    'title' => ['disabled' => 'disabled'],
  ],
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
];

In our exemple pay attention on #options_attributes array where I set the attribute disabled

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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