Are you wondering how to set classes on Drupal 8+'s FAPI checkboxes / radios single options or disable one of them?
Let me help you!
Checkboxes and Radios Form Elements are implemented similarly in Drupals Form API (FAPI):
// Checkboxes:
$form['checkboxes'] = [
'#type' => 'checkboxes',
'#options' => ['blue' => $this->t('Blue'), 'red' => $this->t('Red')],
'#title' => $this->t('Which colors do you like?'),
...
];
// Radios:
$form['my_radios'] = [
'#type' => 'radios',
'#options' => ['blue' => $this->t('Blue'), 'red' => $this->t('Red')],
'#title' => $this->t('Which colors do you like?'),
...
];
As you can see, the options are given by an associative array:
'#options' => ['blue' => $this->t('Blue'), 'red' => $this->t('Red')],
But what if you need to customize the single radio or checkbox inputs? For example to:
- add a class or ID for the checkbox(es) / radio(s) options
- disable a single checkbox or radio
- ...
Then you may first try to modify the #options array, but that doesn't work, and it's not that easy to find out, how that works in Drupal 8+!
I found a lot of complicated solutions suggesting preprocess hooks or preprocess callbacks like this: https://drupal.stackexchange.com/questions/127795/how-to-add-class-to-individual-radio-item-inside-radios
But finally, I found this little hint on the following Drupal API Render element pages:
Element properties may be set on single option items as follows:
$form['settings']['active'][0]['#description'] = $this
->t('Description for the Closed option.');
(https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Checkboxes.php/class/Checkboxes/10 / https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Radios.php/class/Radios/10)
That led me to the following working implementation, which is really simple!
(Although I don't understand why there's not documented very well and isn't really intuitive) 😉
Here's the trick:
You need to add another array keyed by the #options keys:
Setting attributes on radio / checkbox options:
// Set a class on a single radio option:
$form['my_radios']['my_value_key']['#attributes']['class'][] = 'my-custom-radio-option-class';
// Set an ID on a single radio or checkbox option:
$form['my_radios']['my_value_key']['#attributes']['id'] = 'my-custom-radio-option-wrapper-id';
// Disable a single radio or checkbox option:
$form['my_radios']['my_value_key']['#disabled'] = TRUE;
// Set a single radio or checkbox option readonly:
$form['my_radios']['my_value_key']['#readonly'] = TRUE;
// ...
Setting attributes on radio / checkbox option wrappers:
// Set a class on a single radio or checkbox wrapper:
$form['my_radios']['my_value_key']['#wrapper_attributes']['class'][] = 'my-custom-radio-option-wrapper-class';
// Set an ID on a single radio or checkbox wrapper:
$form['my_radios']['my_value_key']['#wrapper_attributes']['id'] = 'my-custom-radio-option-wrapper-id';
// ...
No need for other complicated implementations, you just need to know the trick!