Form submit with radio in table has data in form_state['input'] and not in form_state['values'] While developing a form for Drupal 7, I need a few radio groups, placed inside a table (one radio group per table row). The radios are defined as '#type' =&gt; 'radio' (not radios) and grouped together using the same name attribute per group. Nevertheless, when the form is submitted, the radio selections are not in the $form_state['values'] array, but in $form_state['input'].

As you can see from the screenshots, all data is stored in input, with the radios being outside the 'undefined' array, even though I placed them in $form['undefined'][$key][x]. In values only the select and textfield data is retained.

Any ideas? It's been two days now that I'm trying to resolve this :(
Thank you in advance.

function game_insert_form($form, &amp;$form_state) {
  dpm($form_state, 'form_state');

  $test_data = array(
    '2' =&gt; 'Alfa',
    '4' =&gt; 'Beta',
    '6' =&gt; 'Gamma',
    '8' =&gt; 'Delta',
  );

  $header = array(
      t('Name'),
      array('data' =&gt; t('Existing'), 'colspan' =&gt; 2),
      array('data' =&gt; t('New'), 'colspan' =&gt; 2),
  );
  $form['undefined'] = array(
      '#tree' =&gt; TRUE,
      '#theme' =&gt; 'table',
      '#header' =&gt; $header,
      '#rows' =&gt; array(),
  );
  foreach ($test_data as $key =&gt; $data) {
    // Label
    $label = array('#markup' =&gt; $data);
    $children = array(&amp;$label);
    $row = array(array('data' =&gt; &amp;$label));
    unset($label);
    // radio 0
    $radio0 = array(
      '#type' =&gt; 'radio',
      '#return_value' =&gt; 0,
      '#value' =&gt; 0,
      '#name' =&gt; 'undefined-' . $key . '-radio',
    );
    $children['radio0'] = &amp;$radio0;
    $row[] = array('data' =&gt; &amp;$radio0);
    // dropdown
    $select = array(
      '#type' =&gt; 'select',
      '#options' =&gt; array(0 =&gt; 'Zero', 1 =&gt; 'One'),
      /*'#states' =&gt; array(
        'enabled' =&gt; array(
          ':input[name="undefined-' . $key . '-radio"]' =&gt; array('value' =&gt; 0),
        ),
        'required' =&gt; array(
          ':input[name="undefined-' . $key . '-radio"]' =&gt; array('value' =&gt; 0),
        ),
      ),*/
    );
    $children['select'] = &amp;$select;
    $row[] = array('data' =&gt; &amp;$select);
    // radio 1
    $radio1 = array(
      '#type' =&gt; 'radio',
      '#return_value' =&gt; 1,
      '#value' =&gt; 0,
      '#name' =&gt; 'undefined-' . $key . '-radio',
    );
    $children['radio1'] = &amp;$radio1;
    $row[] = array('data' =&gt; &amp;$radio1);
    // textfield
    $textfield = array(
      '#type' =&gt; 'textfield',
      '#maxlength' =&gt; 40,
      '#size'=&gt; 40,
    );
    $children['textfield'] = &amp;$textfield;
    $row[] = array('data' =&gt; &amp;$textfield);

    $form['undefined'][$key] = $children;
    $form['undefined']['#rows'][] = $row;
    unset($radio0);
    unset($select);
    unset($radio1);
    unset($textfield);
  }
  $form['next'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; t('Test'),
    '#weight' =&gt; 0,
    '#name' =&gt; 'test',
  );
  return $form;
}

function game_insert_form_submit($form, &amp;$form_state) {
  dpm($form_state, 'submit: form_state');
}
At last I managed to find the answer (after a lot of experimentation). The following code works fine for me. I am not sure if everything is needed, but I won't touch it as long as it works.


Pay attetion that I use an associative array for the #rows array, in order to be able to find the correct row without keeping track of indexes.
The most bizzare part is that I had to add $form[$key]['#type'] = 'value'; to hold the selected value.
The '#name' =&gt; $key, is obviously used to group the radios
together per row.
The '#id' =&gt; drupal_html_id($key . '[' . $item . ']'), was also
added, but I'm not sure if it's needed.


Obviously one does not need to use a seperate column for the label, but I display it this way because in my code I use drop downs and other controls instead of the labels shown here.

Here is the code:

function game_test_form($form, &amp;$form_state) {
  dpm($form_state, 'form_state');
  $test_data = array(
    'alfa' =&gt; array(1, 2, 3),
    'beta' =&gt; array(1, 2, 3),
  );
  $header = array(
      t('Name'),
      array('data' =&gt; t('First'), 'colspan' =&gt; 2),
      array('data' =&gt; t('Second'), 'colspan' =&gt; 2),
      array('data' =&gt; t('Third'), 'colspan' =&gt; 2),
  );
  $form['undefined'] = array(
    '#tree' =&gt; TRUE,
    '#theme' =&gt; 'table',
    '#header' =&gt; $header,
    '#rows' =&gt; array(
      // The keys here are used later on for the correct #row insertion
      'alfa' =&gt; array('title' =&gt; t('Alfa')),
      'beta' =&gt; array('title' =&gt; t('Beta')),
    ),
    '#prefix' =&gt; '&lt;div id="game_update_table"&gt;',
    '#suffix' =&gt; '&lt;/div&gt;',
  );
  $table = &amp;$form['undefined'];
  foreach ($test_data as $key =&gt; $data) {
    // This stores the value in the $form_state['values']. It must be outside the table.
    $form[$key]['#type'] = 'value';
    foreach($data as $item) {
      $element = array(
        '#type' =&gt; 'radio',
        // this value will be assigned to the $form_state['values'][$key]
        '#return_value' =&gt; $item,
        '#default_value' =&gt; isset($form_state['values'][$key]) ? $form_state['values'][$key] : 0,
        // Radio group stored in input[#name] with the selected radio's #return_value as value
        '#name' =&gt; $key,
        '#id' =&gt; drupal_html_id($key . '[' . $item . ']'),
      );
      // Attach the radio to the logical tree, so as to be included in $form_state['values']
      $table[$key][$item] = &amp;$element;
      // Attach the radio to the render tree, so as to be rendered.
      $table['#rows'][$key][] = array('data' =&gt; &amp;$element);
      unset($element);
      // Attach its label to the render tree, so as to be rendered.
      $table['#rows'][$key][] = array('data' =&gt; array('#markup' =&gt; 'Label ' . $item));
    }
  }
  $form['next'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; t('Test'),
    '#weight' =&gt; 0,
    '#name' =&gt; 'test',
  );
  return $form;
}
function game_test_form_submit($form, &amp;$form_state) {
  dpm($form_state, 'submit: form_state');
  $form_state['rebuild'] = TRUE;
}