Hi all,

todas I pulled out my hair on a crazy #ajax problem... as anonymous user a FAPI #ajax functionality did not work, but logged in it worked...

I was searching for DC or core bugs... tried out dc_ajax_add_cart module, but had the same problem...

After several hours I found out the §§$%&"§$ reason ... ;)

We had a user login block on the page for anonymous users. Its submit button had the same ID as the commerce_cart_add_to_cart_form submit button: "edit-submit".

It may be discussed where this behaviour should be changed but I think Commerce is probably easier to fix than core. My suggestion would be to set a more unique ID using https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_ht...

$form['submit'] = array(
        '#type' => 'submit', 
        '#value' => t('Add to cart'), 
        '#weight' => 50,
        '#attributes' => array('id' => 'cart-submit'),
        '#id' => 'cart-submit',
      );

Comments

Anybody created an issue. See original summary.

rszrama’s picture

Status: Active » Closed (won't fix)

Unfortunately, we can't really make this change either. This would break any theme currently used by Drupal Commerce users that targets that submit button. My suggestion would be to use hook_form_alter() in your theme to make this change on your site.

Anybody’s picture

Thank you very much for your quick reply. Yes, that's the way we solved it. I just wanted to share my results with you because I thought other people might run into the same problems.

Nevertheless it could be a solution to set the default id ("edit-submit") using the drupal_html_id() function in Drupal commerce so that the ID will only change in the specific case that the ID is on the page twice?

rszrama’s picture

Hmm, I would've expected Drupal core to have a solution for this; does it not append a numeric ID to at least make sure it's valid HTML? There should be many other use cases where more than one form appears on a page (e.g. search block in the header on the user login page).

rszrama’s picture

Ahh, yeah, in fact it does append the numeric ID. I think your issue may really be that you should be checking the array parents instead of just the ID of the element that was submitted.

pawel.traczynski’s picture

I had the same problem. I was having a searchbox printed in theme + list of products with Add to Cart buttons for each of them. Since there were many of these buttons, the solution of setting the '#id' didn't work as it caused duplicated id's ammong the Add to Cart buttons. I ended up doing:

<?php
$form['cart_submit'] = $form['submit'];
unset($form['submit']);
?>

The whole code for AJAXIFYING my add to cart form using my own module was:

<?php
/**
 * Implements hook_form_alter().
 * 
 * - Add support for AJAX add to cart.
 * - Change submit HTML id so it's unique (same id was on searchbox submit).
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if (stristr($form_id, 'commerce_cart_add_to_cart_form_')) {
    //AJAX add to cart
    $form['submit']['#ajax'] = array(
      'callback' => 'MYMODULE_add_to_cart_ajax',
      'wrapper' => 'block-commerce-cart-cart',//for updating cart block
      'effect' => 'none',
      'progress' => array('type' => 'throbber', 'message' => ''),
    );
    $form['#submit'][] = 'MYMODULE_add_to_cart_form_submit';
    
    //Change submit HTML id so it's unique
    $form['cart_submit'] = $form['submit'];
    unset($form['submit']);
  }
}

/**
 * Custom submit handler for add cart form, required by ajax.
 */
function MYMODULE_add_to_cart_form_submit($form, &$form_state) {
  $form_state['rebuild'] = true;
}

/**
 * AJAX callback for add to cart form submit.
 */
function MYMODULE_add_to_cart_ajax($form, &$form_state) {
  //Get updated cart block contents
  global $user;
  $order_id = commerce_cart_order_id($user->uid);
  $cart =  commerce_embed_view('commerce_cart_block', 'default', array($order_id));
  
  $commands = array();

  //Update cart block
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .store-cart', $cart);
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .cart-empty-block', $cart);

  //Call theme status message so these messages wont show on next page reload
  theme('status_messages');

  //Append 'success' confirmation text to HTML
  $commands[] = ajax_command_after('.' . $form['#attributes']['class'][1], '<span class="store-ajax-reply">' . t('Adding done') . '</span>');
  
  return array('#type' => 'ajax', '#commands' => $commands);
}
?>

The above code worked beatifully for me.
I hope it helps someone :)