Trying to change a radio value during form validate I have a form that includes a set of radio inputs, and other fields that will or will not be relevant, depending on which radio option is selected. I'm using #states for client-side UX sugar.

However there are certain conditions, picked up in the validate function that need to change the value the user entered for the radio, and re-present the form with a different option selected. I'm having problems with this, as the form comes back but the option is not changed. e.g. Submitting this should with 'a' selected should change it to 'b' and re-present.

What happens is that the value is set to b, the form rebuilds, but the browser still shows 'a' selected.

&lt;?php
function x_a_form($form, &amp;$form_state) {
  return [
    'switcher' =&gt; [
       '#type' =&gt; 'radios',
       '#options' =&gt; [
           'a' =&gt; 'Aye',
           'b' =&gt; 'Bee', ],
       '#default_value' =&gt; empty($form_state['values']['switcher']) 
                           ? 'a' 
                           : $form_state['values']['switcher'],
    ],
    'submit' =&gt; ['#type' =&gt; 'submit', '#value' =&gt; 'Go' ],
  ];
}

function x_a_form_validate($form, &amp;$form_state) {
  // silly example of a condition...
  if ($form_state['values']['switcher'] == 'a') {
     // Change the value.
     // Nb. form_set_value() is a very long winded way to do just this:
     $form_state['values']['switcher'] = 'b';
     // We will not be saying anything is invalid, but we don't want
     // the form to submit.
     $form_state['rebuild'] = TRUE;
     return;
  }
  // other validation...
}
Did a little more digging. It seems when Drupal (re)builds a form, it sets the element values based on the actual form input ($form_state['input']) and not the form values ($form_state['values']). See _form_builder_handle_input_element. So form_set_value does changes the form value, but it does not update the form input and, therefore, does not get processed how you want it to in this case. While I don't know if this is the "proper" way to do this, but in your form function, you can try throwing in something like:

if (!empty($form_state['values']['myelement']) {
  $form_state['input']['myelement'] = $form_state['values']['myelement'];
}


I tried this with a textfield element, and the value I set using form_set_value was displayed in the textfield when the form was rendered.