Vote up!
Vote down!

Disable Ajax on add to cart form

I have a quite different use case for the add to cart form.

In my case a have a product with 5 attributes. All attributes are term references (with attached images). So I use fancy attributes to display the rendered terms instead of the drop downs or radios.

This is wonderful. By using bulk creation I can generate all product variations by selecting the terms I need for this product.


The ajax refresh on add to cart form is not suitable for me. The customer has to wait about 1s to modify other attributes. The problem is I have a canvas element on the line-item. The canvas element does some image generation based on the images from the term references. Due to the ajax refresh the usability is not good. All my variations have the same price and all variations can be combined. There is no dependency. So I do not need this ajax refresh.

I tried it with all my attributes on line items. This is good but there are disadvantages. For instance I need a line item type for every product. Furthermore I need attributes (term references) for every line item type.

Can someone give me an advice how can I achieve my goal?
Any help appreciated!!!

Asked by: carsten.beyond
on August 9, 2013

3 Answers

Vote up!
Vote down!

In case you haven't found an answer yet, I have a similar situation. This is what I did:

Do a form alter to remove the #ajax callback from the attribute fields. I just used a loop and set the #ajax callback to nothing.

Then override the #submit with my own custom submit.

      foreach($form['attributes'] as $attribute => $v){
          $form['attributes'][$attribute]['#ajax'] = '';
      $form['#submit'][0] = 'MY_CUSTOM_add_to_cart_form_submit';

The reason for overriding the submit is because those ajax calls on attributes will refresh the form and set the hidden product_id field based on the attributes selected on the ajax call. Since that's not going to happen now, we need to find the correct product_id ourselves, before we send it to the normal submit handler.

The following works for my use case. It's pretty direct and some code was borrowed from the #ajax callback function we skipped.

function MY_CUSTOM_add_to_cart_form_submit($form, &$form_state) {
  // easiest way I could find to get the product ids attached to this display was from the from id.  After stripping the text, I explode with _ and I have an array of all the product ids.

  $product_ids = explode('_', str_ireplace('commerce_cart_add_to_cart_form_', '', $form_state['values']['form_id']));

  // Load all the active products intended for sale on this form.
  $products = commerce_product_load_multiple($product_ids, array('status' => 1));
  $attribute_names = $form_state['values']['attributes'];
  // loop through all the product id / attribute combinations and save a matching product id when it's found.
  foreach($products as $product_id => $product) {
    $match = TRUE;
    $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
    foreach($attribute_names as $k => $v) {
      if($product_wrapper->{$k}->raw() != $v) {
        $match = FALSE;
    $product_match = $match ? $product_id : $product_match;

// save the matching product id
  $form_state['values']['product_id'] = $product_match;

// call the original submit handler
  commerce_cart_add_to_cart_form_submit($form, $form_state);

I don't know if this is the best way to do this, but it's working for me and seems pretty direct. In my case, it's limited to one product display and on set of products and a custom line item type. Because of this, I don't expect any problems with the rest of the store.

I hope this helps. If there is a better way I'd love the feedback.

Answer by: sleepingmonk
Posted: Aug 22, 2013
Vote up!
Vote down!

Yep I did something similar.
I unsetted the #ajax properties and added an own validation function. In this function I try to find the matching product and set the product_id. So the submit handler is untouched. works so far.

Answer by: carsten.beyond
Posted: Aug 22, 2013
Vote up!
Vote down!

Yeah it's probably better in the _validate function. Good call.

Answer by: sleepingmonk
Posted: Aug 27, 2013