Discussions

Add to cart with Ajax

I made a simple module (ajax_cart) that alter the add to cart form. The problem is that with this module I can add only one product to the cart. Can someone look at code and try to figure out. Thanks.

Here's the code:

function ajax_cart_form_alter(&$form, &$form_state, $form_id) {
  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',
        'method' => 'replace',
        'effect' => 'fade',
        'progress' => array('type' => 'throbber', 'message' => ''),
      ),
    );
  }
}

function ajax_cart_form($form, $form_state){
  global $user;
  $form_state['rebuild'] = FALSE;
  $order_id = commerce_cart_order_id($user->uid);
  $cart =  commerce_embed_view('commerce_cart_block', 'default', array($order_id));
  $commands = array();
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .cart-empty-block', $cart);
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .view-commerce-cart-block', $cart);
  return array('#type' => 'ajax', '#commands' => $commands);
}
Posted: Feb 23, 2012

Comments

supergogy on February 27, 2012

I looked at that module but it doesn't have funcionallity that I need.
When the user click on the Add to Cart form (on page or in the views) I need to change state in the cart block.
Because of that I made my own module, but I can add only one product to cart.

Thanks

5t4rdu5t on April 16, 2012

I've found the way to make your code work for multiple submissions. It just needed to flush the form caches. It's working very well for me, so anyone looking for ajaxy buttons may use it as well:

<?php

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);
}

?>

naitan on April 21, 2012

If like me you wanted to display the add to cart message you can add something like this to the ajax_cart_form() function
$commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));

It will become

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);
  $commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));
  return array('#type' => 'ajax', '#commands' => $commands);
}

Works perfectly for me.

2pha on July 3, 2012

I have 2 products on the same product display, using the above code it works as expected when you add a product that is on the page when it first loads. But when you change the product (with a dropdown selecting a color in my case) and you try to add this other product, I get the error:
EntityMalformedException: Missing bundle property on entity of type commerce_line_item. in entity_extract_ids() (line 7539 of /var/www/mysite/includes/common.inc)

2pha on July 3, 2012

I got it fixed with the code below.
Instead of resetting the forms cache, I rebuild the form.

<?php

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' => ''),
      ),
    );
   
$form['#submit'][] = 'ajax_cart_form_rebuild_submit';
  }
}

function
ajax_cart_form_rebuild_submit($form, &$form_state){
 
$form_state['rebuild'] = TRUE;
}

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();
 
 
$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);
 
$commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));
  return array(
'#type' => 'ajax', '#commands' => $commands);
}

?>

nelslynn on July 20, 2012

- Is there a way to not display the "Added to cart" message multiple times when the "Add to Cart" button is clicked. The new message should replace the previous message. As the code is now, a new message is displayed each time a new SKU is added from the same product page.

Nice contribution... thank you for this!

cibson on June 16, 2013

With this command I remove the last message before adding the new one:

 
$commands[] = ajax_command_remove('.messages status');
$commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));

bendev on March 25, 2013

I got some problem if the page with the form is put in cache. The only way to solve it as to flush the page cache.
I disabled caching of the page to solve this; Any idea what's the best approach to setup caching of pther pages ? or to disable caching of a specific page ?
thanks.

Anjan Doshi on September 10, 2014

My Product view is opening in Lightbox2 Overlay using : VIEW DEAL

Above code is not working for Drupal messages in Lightbox2. Drupal messages are not displaying in Lightbox2. When I refresh the page, I can see messages.

achauhan on September 17, 2013

Helped me lot, in updating cart without refreshing page. Used the same code with little changes for removing product from the cart without refreshing page.

sight on August 25, 2012

hello guys i have a problem with this code my button doesn't work correctly for anonymous users, works with the second third time.

victorv on January 10, 2013

I made it the easy way and put this in my template.php file... but when i clear the caches it only shows the text "array".

If i just upload it and dont clear caches it works like a charm. Any ideas?

<?php
/* ----------Cart manipulation------------------------------ */
function MYTHEME_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('BUY TEXT'),
     
'#type' => 'submit',
     
'#ajax' => array(
       
'callback' => 'MYTHEME_form',
       
'wrapper' => 'block-commerce-cart-cart',
       
'effect' => 'fade',
       
'progress' => array('type' => 'throbber', 'message' => ''),
      ),
    );
   
$form['#submit'][] = 'MYTHEME_form_rebuild_submit';
  }
}

function
ishop_form_rebuild_submit($form, &$form_state){
 
$form_state['rebuild'] = TRUE;
}

function
MYTHEME_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();

 
$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);
 
$commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));
  return array(
'#type' => 'ajax', '#commands' => $commands);
}
/* --------------------------------------------------------- */
?>

neighborhoodsix on March 21, 2013

Is there a way to make this work without altering other form submissions? I use a global filter on the same page as my catalog and this code makes that filter submission use ajax in addition to the "add-to-cart" buttons.