Ajax form that changes a button value When a user pushes a button element marked with ajax, I would like the callback to modify the button value (text shown on button), and have it updated both in the browser and the form state. Updating in the browser is easy by return an ajax_command_replace call. But I'm not having any luck with getting the form updated to remember the updated button value the next time the button gets pushed.

It seems the way the ajax form is built, that the initial value of the button gets hardcoded where the callback function in the javascript page gets defined, which probably explains why the button element returned to the ajax callback does not match with the value it shows in the browser (after I changed it with the ajax_command_replace).

But I can live with that, as long as I can get the form (or form_state) to actually remember the new value of the button element from a previous invocation of the callback.

I've also tried modifying the form/form_state values in the form validate hook, but without success.

So, despite already knowing this does not work, the following code tries to illustrate what I'm trying to do:

function testajax_callback($form, &amp;$form_state) {
  $form['mybtn']['#value'] = 'New value';
  return array(
    '#type' =&gt; 'ajax',
    '#commands' =&gt; array(
      ajax_command_replace('#mybtnwrapper' =&gt; drupal_render($form['mybtn']))
  );
}


Any help on how to do this the Drupal 7 way would be appreciated.

update 1:

Got a hint on the Drupal Forums. The following code is probably more according to Drupal 7 design and style:


function betapp_testajax_callback($form, &$form_state) {
  $form['mybtn']['#value'] = 'New value';
  return $form['mybtn'];
}

function betapp_testajax_form($form, &$form_state) {
  $form['mybtn'] = array(
    '#type' => 'button',
    '#id' => 'mybtn',
    '#prefix' => '',
    '#suffix' => '',
    '#default_value' => 'Default value',
    '#ajax' => array(
      'callback' => 'betapp_testajax_callback',
      'wrapper' => 'testajaxwrapper',
      'method' => 'replace',
      'effect' => 'fade'
    )
  );
  return $form;
}


The code manages to change to appearance of the button (button value), but when pressing the button with the updated value, the old one is still the one sent, so effectively, no values in the form has changed, only the button appearance.

It may have something to do with hardcoded values in the callback definitions in the html page (which is only loaded once). I find entries such as these:


{"callback":"betapp_testajax_callback","wrapper":"testajaxwrapper","method":"replaceWith","effect":"fade","event":"mousedown","keypress":true,"url":"\/d7\/system\/ajax","submit":{"_triggering_element_name":"op","_triggering_element_value":"Default value"}}


If _triggering_element_value is used regardless of the actual value of the element, that explains why the new value is not picked up. Maybe the _triggering_element_value should be looked up at runtime when the callback gets activated?

Any ideas on workarounds/fixes?
The short solution to my original question can be coded like this:


function betapp_testajax_callback($form, &$form_state) {
  return $form['mybtn'];
}

function betapp_testajax_form($form, &$form_state) {
  dd('');
  dd('betapp_testajax_form');
  $form['mybtn'] = array(
    '#type' => 'button',
    '#id' => 'mybtn',
    '#default_value' => 'Ignored default value',
    '#prefix' => '',
    '#suffix' => '',
    '#ajax' => array(
      'callback' => 'betapp_testajax_callback',
      'wrapper' => 'testajaxwrapper',
      'method' => 'replace',
      'effect' => 'fade'
    )
  );
  $prevval = '(blank)';
  if (isset($form_state['values']['mybtn'])) {
    $prevval = $form_state['values']['mybtn'];
    dd('prevval : ' . $prevval);
  }

  $form['mybtn']['#value'] = 'Newval ' . rand(0, 100);

  dd('newval  : ' . $form['mybtn']['#value']);
  return $form;
}


which lead to output like:


betapp_testajax_form
newval  : Newval 48

betapp_testajax_form
prevval : Newval 48
newval  : Newval 62

betapp_testajax_form
prevval : Newval 62
newval  : Newval 0

betapp_testajax_form
prevval : Newval 0
newval  : Newval 59


My usage requires a little bit more; whenever a button is changed, there are other elements that should be updated as well. But I think I managed to pull it together (looks correct for now anway), and in the spirit of sharing, here's what I managed to glue together:


function betapp_testajax_callback2($form, &$form_state) {
  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace('#mybtn', drupal_render($form['mybtn'])),
      ajax_command_replace('#inp', drupal_render($form['inp']))
    )
  );
}

function betapp_testajax_form2($form, &$form_state) {
  dd('');
  dd('betapp_testajax_form');
  $form['mybtn'] = array(
    '#type' => 'button',
    '#id' => 'mybtn',
    '#default_value' => 'Ignored default value',
    '#prefix' => '',
    '#suffix' => '',
    '#ajax' => array(
      'callback' => 'betapp_testajax_callback',
      'wrapper' => 'testajaxwrapper',
      'method' => 'replace',
      'effect' => 'fade'
    )
  );
  $prevval = '(blank)';
  if (isset($form_state['values']['mybtn'])) {
    $prevval = $form_state['values']['mybtn'];
    dd('prevval : ' . $prevval);
  }

  $form['mybtn']['#value'] = 'Newval ' . rand(0, 100);

  $form['inp'] = array(
    '#type' => 'textfield',
    '#value' => $prevval,
    '#id' => 'inp'
  );
  dd('newval  : ' . $form['mybtn']['#value']);
  return $form;
}


This code updates the original button, and sets the input field to the previous value of the button. My case requires modifying other buttons, but hopefully that will work. If not, I'll bug you on this thread again.

Thank you.