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;
}
  • 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 '12 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 – Marius Ilie Mar 9 '12 at 21:59
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);
}
|improve this answer|||||
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”.

|improve this answer|||||
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);
}
|improve this answer|||||
-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.

|improve this answer|||||
  • AHAH was (thankfully) removed from Drupal 7, it can't be used any more. – Clive May 16 '12 at 12:53
  • Right, I missed the D7 part :( – acouch May 16 '12 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.

|improve this answer|||||
  • I already use the quantity field. But I need to be able to display the form again after submit, and it should work. – Marius Ilie May 16 '12 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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