Hi

I would think this should be pretty simple, but I cannot get it to work - maybe someone else can figure it out:

I have a form with an ajax enabled submit button. Initially the button value is "Activate", when it is pressed the callback runs a script which takes the button value as an argument, and then changes the button value to "Deactivate". When it is pressed again it should again run the script and then change the button value back to "Activate", etc., etc.
First time it is pressed, it seems to work - the script is called and the value changes. But it is only the html part printed to the page that is being changed - the actual value in the form array isn't changed. And that shows by every other click you make, the button will not change.

The form is initially called from somewhere else with some custom variables - $cid is unique. $activestate is either "Activate" or "Deactivate".

Here is the code - can you see what I'm doing wrong?

function mymodule_form($form, &$form_state, $cid, $activestate) {

  $form['submit'] = array(
    '#type' => 'submit',
    '#name' => $cid,
    '#id' => $cid,
    '#value' => $activestate,
    '#ajax' => array(
      'callback' => 'mymodule_callback',
      'wrapper' => 'mymodule_button'.$cid,
      'method' => 'replace',
      'effect' => 'fade',
    ),
    '#prefix' => '<div id="mymodule_button'.$cid.'">',
    '#suffix' => '</div>',
  ); 
  return $form;
}

function mymodule_callback($form, $form_state) {
  // get value from the triggering element
  $value = $form_state['triggering_element']['#value'];
  $cid = $form_state['triggering_element']['#name'];

  // run the script
  some_script($value); 

  // change the button value
  if ( $value == 'Activate') {
    $form['submit']['#value'] = 'Deactivate'; 
  } else {
    // I read some where that you might have to set several variables
   // in the element's array, before drupal-ajax would see the change
   // so that's what I try here  - but it doesn't matter which way I do it.
    $form['submit'] = array (
      '#value' => 'Activate',
      '#type' => 'submit',
      '#name' => $cid,
      '#id' => $cid,
      '#ajax' => array(
        'callback' => 'mymodule_callback',
        'wrapper' => 'mymodule_button'.$cid,
        'method' => 'replace',
        'effect' => 'fade',
      ),
      '#prefix' => '<div id="mymodule_button'.$cid.'">',
      '#suffix' => '</div>',

    );
  }
    
  return $form['submit'];
}

Comments

jaypan’s picture

All changes need to be made in the form definition, based on the values in $form_state['values']. You are making changes in your ajax callback - these will not work, and this is why your code is not working.

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

andersiversen’s picture

Thanks for your answer Jaypan. I've tried that before and it didn't work (it was as if the form wasn't rebuild during the callback). But I tried again, and then discovered that it shouldn't be '#type' => 'submit', but instead '#type' => 'button' - then it works!
Thanks :) Here's the final code that works:

function mymodule_form($form, &$form_state, $cid, $activestate) {

  $form['submit'] = array(
    '#type' => 'button',
    '#name' => $cid,
    '#id' => $cid,
    '#ajax' => array(
      'callback' => 'mymodule_callback',
      'wrapper' => 'mymodule_button'.$cid,
      'method' => 'replace',
      'effect' => 'fade',
    ),
    '#prefix' => '<div id="mymodule_button'.$cid.'">',
    '#suffix' => '</div>',
  );

  if (isset($form_state['values']['submit'])) {
    $value = $form_state['values']['submit'];
    if ($value == 'Deactivate') {
      $form['submit']['#value'] = 'Activate';
    } else {
      $form['submit']['#value'] = 'Deactivate';
    }
  } else {
    // first time the form is built.
    $form['submit']['#value'] = $activestate;
  }

  return $form;
}

function mymodule_callback($form, $form_state) {
  // get value from the triggering element
  $value = $form_state['triggering_element']['#value'];
  // run the script
  some_script($value); 

  return $form['submit'];
}

- I've got a new pal - Drupal. We play all the time.

Mike Vranckx’s picture

Indeed, clicking a submit will execute the submit handler of the form and rebuilds the form with an empty $form_state (as it would render it on a default page load).

To disable the submit handler execution (or enable it on button types), you can use the #executes_submit_callback property.

// Disable submit_callback submit buttons
$form['submit'] = array(
    '#type' => 'submit', 
    '#value' => t('Submit'),
    '#executes_submit_callback' => false,
);

// Enable submit callback on classic buttons
$form['button'] = array(
    '#type' => 'button',
    '#value' => t('Save changes'),
    '#executes_submit_callback' => true,
    '#submit' => array('my_form_save_submit'),
);
gusantor’s picture

This is so valuable information !

thanks !