I need to modify the html code of radio buttons generated by Ubercart Attributes. So I want to do it using hook_form_alter().

enter image description here

If I dsm() the $form I need to change using hook_form_alter() I get this

attributes (Array, 7 elements)
#theme (String, 24 characters ) uc_attribute_add_to_cart
#id (String, 42 characters ) uc_product_add_to_cart_form-472-attributes
    #type (String, 6 characters ) radios
    #default_value (NULL)
    #options (Array, 4 elements)
        0 (String, 7 characters ) Color 1
        1 (String, 7 characters ) Color 2
        2 (String, 7 characters ) Color 3
        3 (String, 8 characters ) Color 17
    #ajax (Array, 2 elements)
    #title (String, 4 characters ) yeah
    #description (String, 0 characters )
    #required (String, 1 characters ) 1

I can apply a #prefix/#suffix to div wrapping all radio buttons:

<div class="test">
  <div class="form-item form-type-radios form-item-attributes-8">
     <div class="form-label">
        <div class="element-inner">
           <div class="el">
               <div id="edit-attributes-8" class="form-radios my-custom-class">
               <div class="form-item form-type-radio form-item-attributes-8">
               <div class="form-item form-type-radio form-item-attributes-8">
               <div class="form-item form-type-radio form-item-attributes-8">
              <div class="form-item form-type-radio form-item-attributes-8">
        <div class="description"></div>

I proceed like that for this result:

$form['attributes']['8']['#prefix'] = '<div class="test">';
$form['attributes']['8']['#suffix']= '</div>'; 

The problem is that I want to apply this #prefix/#suffix to all options instead, I tried something like that but it doesn't work:

$form['attributes']['8']['#options'][0]['#prefix'] = '<div class="test">';
$form['attributes']['8']['#options'][0]['#suffix']= '</div>'; 

So is it possible to do it this way? Any suggestion?


In your form_alter you can tell drupal to use your custom theme_radio like this:

$form['attributes']['#theme'] = 'MYCUSTOM_radio_theme';

Then in 'MYCUSTOM_radio_theme:

$element = $variables['element'];

$element['#attributes']['type'] = 'radio';

element_set_attributes($element, array('id', 'name','#return_value' => 'value'));

if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] == $element['#return_value']) {
    $element['#attributes']['checked'] = 'checked';

  _form_set_class($element, array('form-radio'));

  return '<div class="test"><input' . drupal_attributes($element['#attributes']) . ' /></div>';
  • Thanks for this information. Unfortunately I was not able to do it this way. I was just able to call theme_radio() from my template.php file using this name: mytheme_radio(). Is it possible to call 'MYCUSTOM_radio_theme' from .module file? How?? – 118218 Oct 6 '14 at 14:12
  • you need to register your theme function with hook_theme – 2pha Oct 7 '14 at 3:40
  • @2pha, can you give more info about how to register a theme function in .module files? I tried something like declaring two functions: MY_MODULE_theme($existing, $type, $theme, $path) and theme_custom_radio(). – 118218 Oct 8 '14 at 12:00
  • 1
    I think this page will help you to understand how to write your hook_theme: hook_theme – Akko Oct 8 '14 at 14:48

There is an easy answer to this, but I was very nearly driven insane trying to find it because it doesn't appear to be documented anywhere.

$form['input']['option_key'] = array(
  '#prefix' => '',
  '#suffix' => '',

This is counter-intuitive because it creates an entirely new array for #prefix and #suffix, but I swear it works. In OP's case you would use $form['attributes'][0] to get the first option ('attributes' appears to be the name of the radio button collection, not the form's #attributes array). If it were using strings as array keys you'd use $form['attributes']['option_name'].

I imagine you can do some other interesting things too.

  • This is awesome, and should be the answer! – Collins Feb 9 '17 at 12:24
  • oops, i got ahead of myself. This doesnt work for checkbox options, as you cannot set a #value or #title for the label, and so the ley > label relationship does not work. – Collins Feb 9 '17 at 12:33

Maybe you could override the theme_radio function instead of using form_alter.


Since I can't comment, what @taburk has said is by far the best option. A note of point though, this method can ONLY be done with a hook_form_alter (or hook_form_FORM_ID_alter) as the form array must already exist.

Also, in your form alter remember that as the array already exists you need to append the prefix/suffix keys to it, not overwrite the existing array.

if($form_id == 'my_form_id'){
        foreach($form['my_radio_field']['#options'] as $macname => $thememarkup) {
            $form['my_radio_field'][$macname]['#prefix'] = '<div class="col-md-6">';
            $form['my_radio_field'][$macname]['#suffix'] = '</div>';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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