Hi there,

I stuck with form element theming.
In my form I need radio buttons which indicate a particular colour
and so I thought of wrapping each radio-input form field with
a table cell with the background of whatever "yellow, green, blue, ...".

I tried this:

$colours = array(
   'red',
   'green',
   'blue',
   ...
);

...

function colour_theme() {
  	return array(
 		'colour_radios' => array(
 			'arguments' => array('element' => NULL),
 		),
	);
}

function colour_form($form, &$form_state) {
   global $colours;

   ...

   $form['favouritecolour'] = array(
        '#type' => 'radios',
        '#title' => t('Your favourite colour'),
        '#options' => $colours,
	'#theme' => array('colour_radios'),
   );
}

The form shows all radiobuttons listed up each one below the other - ok.
But how do I manage to pass the necessary form element to this funtion in my .module-File?

function theme_colour_radios($element) {
  	$keys = array_keys($element['#options']);
  	$type = $element[$keys[0]]['#type'];
 
  	foreach ($keys as $key) {
  	   $output .= '<td style="background: '.$key.'">';
    	   $output .= theme('colour_radios', $element[$key]);
  	   $output .= '</td>';
  	}
 
  	return $output;
}

$element should countain $form['favouritecolour'], but it doesn't.

Any advice on this?

Many thanks
Soezkan

Comments

ayesh’s picture

#theme do not need to be an array.
Try this
'#theme' => 'colour_radios'

selimoezkan’s picture

Hi Ayesh,

thanks for your reply.

I tried '#theme' => 'colour_radios'. It makes no difference
since the whole:

function theme_colour_radios($element) {
      $keys = array_keys($element['#options']);
      $type = $element[$keys[0]]['#type'];
      foreach ($keys as $key) {
         $output .= '<td style="background: '.$key.'">';
           $output .= theme('colour_radios', $element[$key]);
         $output .= '</td>';
      }
      return $output;
}

... is not called at all. It makes no difference if I indicate it in my .module-File, or leave it. It has no effect on the output.

Maybe the funtion is at the wrong place? Should it be somewhere in the themes folder?

Many thanks
Soezkan

Mike Vranckx’s picture

You need to add a render element definition in your theme declaration, otherwise your theme callback will never be called.

Try like this:

function colour_theme() {
      return array(
         'colour_radios' => array(
             'render element' => 'element'
         ),
    );
}
ayesh’s picture

Great catch!
you can also use `render element` form, to get parent stuff as well.

selimoezkan’s picture

Thank you for your reply.
Hm, what a pity, but I still can't manage to give a background colour to the radios.

This is the code I try to work with - and as I am new with module development, I believe I forgot something important.

/**
 * Implements hook_permission
 */
function personality_test_permission() {
    return array(
		'use personality-test calculation' => array(
			'title' => t('personality-Test'),
			'description' => t('Allow users to use the personality-Test calculations.'),
		),
	);
}


/**
 * Implements hook_menu
 */
function personality_test_menu() {
    $items = array();
    $items['applications/personality-test'] = array(
        'title' => 'personality-Test',
        'type' => MENU_NORMAL_ITEM,
        'access arguments' => array('use personality-test calculation'),
        'page callback' => 'drupal_get_form',
        'page arguments' => array('personality_test_form'),
    );
    return $items;
}

/**
 * Implements hook_theme
 */
function personality_test_theme() {
      return array(
         'colour_radios' => array(
             'render element' => 'element'
         ),
    );
}

/**
 * Implements a form
 */
function personality_test_form($form, &$form_state) {
	global $colours;
	$form = array();

	/* NAME, EMAIL, GENDER */
	$form['aboutyou'] = array(
		'#title' => t('About you'),
		'#type' => 'fieldset',
		'#description' => t('The following data is required in order to determine your personality-conditions.'),
		'#collapsible' => TRUE,
		'#collapsed' => FALSE
	);
	
    $form['aboutyou']['firstname'] = array(
		'#prefix' => '<p>',
		'#suffix' => '</p>',
        '#type' => 'textfield',
        '#title' => t('First name'),
        '#size' => 20,
        '#maxlength' => 50,
    );
	
    $form['aboutyou']['lastname'] = array(
		'#prefix' => '<p>',
		'#suffix' => '</p>',
        '#type' => 'textfield',
        '#title' => t('Last name'),
        '#size' => 20,
        '#maxlength' => 50,
    );

    $form['aboutyou']['email'] = array(
		'#prefix' => '<p>',
		'#suffix' => '</p>',
        '#type' => 'textfield',
        '#title' => t('Email'),
        '#size' => 20,
        '#maxlength' => 50,
    );

    $form['aboutyou']['gender'] = array(
		'#prefix' => '<p>',
		'#suffix' => '</p>',
        '#type' => 'radios',
        '#title' => t('Gender'),
        '#options' => array(
			'female' => t('female'),
			'male' => t('male'),
		),
		'#default_value' => 'female',
    );
	
	/* BIRTHDATE */
    $form['aboutyou']['birthdate'] = array(
		'#prefix' => '<p>',
		'#suffix' => '</p>',
        '#type' => 'fieldset',
		'#description' => t('Your date of birth.'),
		'#collapsible' => FALSE
    );	
    $form['aboutyou']['birthdate']['birthday'] = array(
		'#prefix' => '<div style="float: left; padding: 0 20px 0 0">',
		'#suffix' => '</div>',
        '#type' => 'textfield',
        '#title' => t('Day of birth'),
        '#size' => 2,
        '#maxlength' => 2,
    );
    $form['aboutyou']['birthdate']['birthmonth'] = array(
		'#prefix' => '<div style="float: left; padding: 0 20px 0 0">',
		'#suffix' => '</div>',
        '#type' => 'textfield',
        '#title' => t('Month of birth'),
        '#size' => 2,
        '#maxlength' => 2,
    );
    $form['aboutyou']['birthdate']['birthyear'] = array(
		'#prefix' => '<div style="margin: 0 0 0 0">',
		'#suffix' => '</div>',
        '#type' => 'textfield',
        '#title' => t('Year of birth'),
        '#size' => 4,
        '#maxlength' => 4,
    );

	/* FAVOURITE COLOURS */
    $form['aboutyou']['colours'] = array(
		'#prefix' => '<table cellpadding="4" cellspacing="3"><tbody>',
		'#suffix' => '</tbody></table>',
        '#type' => 'fieldset',
		'#description' => t('Your favourite colour.'),
		'#collapsible' => FALSE
    );
    $form['aboutyou']['colours']['favouritecolour'] = array(
        '#type' => 'radios',
        '#options' => $colours,
		'#theme' => 'colour_radios',
    );

    return $form;
}

/*
 * Theme Output
 */
function theme_colour_radios($element) {

    $keys = array_keys($element['#options']);
    $type = $element[$keys[0]]['#type'];
 
  	// Start wrapper div for the group.
    foreach ($keys as $key) {
   	$output .= '<td style="background: '.$key.'">';
        $output .= theme('colour_radios', $element[$key]);
        $output .= '</td>';
    }
	  
    return $output;
}

Any idea? It seems theme_colour_radios($element) is never been called.

Many thanks
Soezkan

Mike Vranckx’s picture

Your theme_colour_radios is called but your implementation is not really correct. The theme definition of the render element is element which means that all data passed as argument is available within the $variables['element'].

Here is an example of a more correct implementation which could help you further.

function theme_colour_radios($variables) {
	$element = $variables['element'];
	
	$output = '<table><tr>';
	foreach ($element['#options'] as $option => $value) {
		$output .= '<td style="background-color: '. $option . ';">';
		$output .= drupal_render($element[$option]);
		$output .= '</td>';
	}
	$output .= '</tr></table>';
	
	return $output;
}
selimoezkan’s picture

Many many thanks!

I could solve it with your help.

Some things I added and now it works (added the global $colours-Array containing all hexdec-colour codes and changed the $options parameter in the formatting attributes of the table cell to an array-index, see below):

function theme_colour_radios($variables) {
    global $colours;
	
    $element = $variables['element'];
    $output = '<table><tr>';
    foreach ($element['#options'] as $option => $value) {
        $output .= '<td style="background-color: #'.$colours[$option].';">';
        $output .= drupal_render($element[$option]);
        $output .= '</td>';
    }
    $output .= '</tr></table>';
    return $output;
}

The only last thing I wonder is: How can I remove the hexdec codes from within the table cells beside the radiobuttons?
I only need the background colour and the value of the radio.

http://www.selimoezkan.com/files/images/snap_002.jpg

Thanks again.

Bests
Soezkan

selimoezkan’s picture

I solved it now like this:

function theme_colour_radios($variables) {
	global $colours;
	$counter = 0;
	
    $element = $variables['element'];
    $output = '<tr>';
    foreach ($element['#options'] as $option => $value) {
    	$counter++;

        $output .= '<td style="width: 57px; text-align: center; background-color: #'.$colours[$option].';">';
        $output .= drupal_render($element[$option]);
		$output = preg_replace('/\>[0-9a-fA-F ]+\<\/label\>/', '></label>', $output);

		$output = preg_replace('/name\=\"favouritecolour\" value\=\"[0-9]+\"/', 'name="favouritecolour" value="#'.$colours[$option].'"', $output);
		if($counter % 12 == 0) $output .= '</tr><tr>';
    }
    $output .= '</tr>';
    return $output;
}
selimoezkan’s picture

Now I have a new issue: How can I put the #default value of a radio button (namely "selected")
after submitting my form?
I tried with global $form_state, but nothing delivered.

Any ideas?

Many thanks
Soezkan

jaypan’s picture

As you said, now you have a new issue. New issues deserve new threads.

Contact me to contract me for D7 -> D10/11 migrations.

selimoezkan’s picture

You're right.

Here is the new post:
https://drupal.org/node/2216091

Many thanks
Soezkan