1

I have a form which consists of one submit button (Add to cart). I made it submit via AJAX but the problem is that when I press the button the second or third (and so on) times, the submit handler doesn't execute. I think this happens because the form_build_id and form_token fields should be rebuilt.

Do you have any idea on how I can achieve this functionality?

This is the code I am using.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'my_form_id') {
    $form['submit']['#ajax'] = array(
      'callback' => 'mymodule_ajax_form_callback',
      'wrapper' => 'my_form_wrapper',
    );

    $form['#prefix'] = '<div id="my_form_wrapper">';
    $form['#suffix'] = '</div>';
  }
}

function mymodule_ajax_form_callback($form, &$form_state){
  return $form;
}
2
  • To clarify, you want users to be able to click multiple times to add the same item multiple times to the cart? How are you performing the AJAX submittal? Are you using the D7 AJAX form elements, a custom script, other?
    – areynolds
    Mar 9, 2012 at 18:18
  • yeah, I want users to add same product multiple times. I'm using the form's ajax api. something like: $form['submit']['#ajax'] = array(); The ajax callback is a function which returns an ajax command Mar 9, 2012 at 21:59

5 Answers 5

2
+50

As reported on drupalcommerce.org, the trick is to clear the form and form state caches in your AJAX callback.

The following is a working code example taken from that post:

function ajax_cart_form_alter(&$form, &$form_state, $form_id) {
  // Add ajax property to Add to Cart button
  if (strstr($form_id, 'commerce_cart_add_to_cart_form')) {
    $form['submit'] = array(
      '#value' => t('Add to Cart'),
      '#type' => 'submit',
      '#ajax' => array(
        'callback' => 'ajax_cart_form',
        'wrapper' => 'block-commerce-cart-cart',
        'effect' => 'fade',
        'progress' => array('type' => 'throbber', 'message' => ''),
      ),
    );
  }
}

function ajax_cart_form($form, &$form_state){
  global $user;
  $order_id = commerce_cart_order_id($user->uid);
  $cart =  commerce_embed_view('commerce_cart_block', 'default', array($order_id));
  $commands = array();

  // The next line allows different quantities 
  // to be submitted each time
  unset($form['quantity']['#value']);

  // Clear form and form state cache
  $form_state = form_state_defaults();
  $form_build_id = $_POST['form_build_id'];
  form_set_cache($form_build_id, $form, $form_state);

  $commands[] = ajax_command_replace('#block-commerce-cart-cart .view-commerce-cart-block', $cart);
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .cart-empty-block', $cart);
  return array('#type' => 'ajax', '#commands' => $commands);
}
0
0

First of all, a clean form will work correctly. So, the problem is with altering your form.
Try to play with params #ajax_processed, #processed, #executes_submit_callback.
This code can be helpful in some cases:

// Make AJAX to work
unset($form['submit']['#ajax_processed']);

Commerce cart

As I see tag on your question, I have tested your AJAX on standard commerce cart form:

/**
 * Implements hook_form_FORM_BASE_ID_alter().
 */
function mymodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state) {
  $form['submit']['#ajax'] = array(
    'callback' => 'mymodule_ajax_form_callback',
    'wrapper' => 'my_form_wrapper',
  );

  $form['#prefix'] = '<div id="my_form_wrapper">';
  $form['#suffix'] = '</div>';
  $form['#submit'][] = 'mymodule_form_commerce_cart_add_to_cart_form_submit';
}

function mymodule_ajax_form_callback($form, &$form_state) {
  return $form;
}

function mymodule_form_commerce_cart_add_to_cart_form_submit(&$form, &$form_state) {
  // Ask to rebuild form
  $form_state['rebuild'] = TRUE;
}

AJAX callback is working correctly in this case, but submission of the form are processed only once. So we can rebuild a form to work with the same form again.
Note that standard message “Product added to your cart.” is shown by default Commerce Rules configuration on event “After adding a product to the cart”.

0

The following command replaces the form with a fresh one on every ajax submit and it works great for us:

function mymodule_commerce_ajax_cart_callback($form, &$form_state){
  $form = drupal_rebuild_form($form['#form_id'], $form_state, $form);
  ...
  $commands[] = ajax_command_replace('.' . drupal_html_class($form['#form_id']), drupal_render($form));
  ...
  return array('#type' => 'ajax', '#commands' => $commands);
}
-1

I would suggest using AHAH. It resubmits the entire form when adding the new element so you don't run into the problem you describe above.

2
  • AHAH was (thankfully) removed from Drupal 7, it can't be used any more.
    – Clive
    May 16, 2012 at 12:53
  • Right, I missed the D7 part :(
    – acouch
    May 16, 2012 at 13:39
-1

Instead of using AJAX on the form I would instead add a Quantity field into the Add to cart form so that the user can both add multiple items and also keep track of how many they add. I believe e-cmmerce solutions may prevent you from clicking the Add to cart multiple times to prevent people accidentally adding more than one product as money is involved, though not sure if this is your problem.

1
  • I already use the quantity field. But I need to be able to display the form again after submit, and it should work. May 16, 2012 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.