Forms API is great, let me start there. However there are some cases where you want to ... ahem, go around it. One such cases is with checkboxes (where you have a number of checkboxes), specifically when you want to alter just one of the set. Here's how to fix that!
The posts I've found around the net talk about changing the array by setting elements that will appear once the form is processed. Well that just didn't work for me, so I had to take the long route -- which always works.
This method is based around the #pre_render method of elements. That is, each form element can assign callbacks before it's actually converted to flat HTML. Which is great for our purpose! Here's an example form, with checkboxes, and conditional #pre_render assignement:
function mymodule_form( ) { [...] $countries = mymodule_getcountries(); $form['group-'.$continent][$continent] = array( '#type' => 'checkboxes', '#title' => t($continent), '#options' => $countries, '#multicolumn' => array('width' => 2), '#checkall' => true, '#pre_render' => array('mymodule_checkelement'), ); [...] } function mymodule_checkelement($element) { [...] $not_allowed_countries = mymodule_getcountries(); //Note that options are in the element array foreach($element as $key=>&$properties) { if ( in_array($key,$not_allowed_countries)) { $properties['#attributes']['disabled'] = true; } } return $element; }
What the above code does -- it has a form builder function (which I assume you know all about), and defined the #pre_render callback. The function is then called and can perform processing to each individual option. In the above example, I've added some logic to disable checkboxes for countries that are not allowed to be checked.
I hope this helps someone else out, it took me almost half a day to make this manageable!
Image from here