On AJAX enabled Views with exposed filters or pagers the "Add to Cart" button does not work properly.

After an AJAX call, the add-to-cart form action changes to views/ajax, so if you press the button, only a JSON output will be displayed.

This is a Views AJAX issue. Any form being shown in a Views using AJAX will have it's action path changed.

Steps to reproduce:

  1. Create a View that shows your Product Displays.
  2. Set the View to use a pager, display 1 item
  3. Ensure the "Add to Cart" form is being displayed. This can be done using rendered entity, or when using fields adding the add to cart form field element
  4. Under Advanced, set the View to use AJAX.
  5. Now when you view the View, and use the pager, and then click "Add to Cart", you will get the JSON views/ajax page.

Comments

rszrama’s picture

Category: Bug report » Support request
Status: Active » Closed (won't fix)

This actually has nothing to do with Commerce and is really just a limitation of Views itself. When a form is built in Drupal, its action is always whatever URL generated the form. When you make the Ajax request, it POSTs to views/ajax, so if the View output has a form in it, that's going to be its action. The simplest workaround is to disable the Ajax functionality for the View; next is to theme a link to look like an Add to Cart button instead that takes you to the product page; if you're feeling up to it, you can also use the Rules link module to make that link an actual Add to Cart button. Making our Views field work with Ajax Views isn't in the cards at the moment.

eFeS’s picture

The only problem, that I do not want to go to the product page, neither make a link to look like an Add to cart button. I want the selected product to add to the cart from the listing page.

OK, but I realized, that this is ponintless to cointinue this way. Is there any chance to solve this? Which module needs a patch, for example? I'm not a programming guru, but if there is no other solution, I could give a try to fix it myself. Or is it impossible?? :)

donutdan4114’s picture

One solution to this, is a quick custom menu item that can handle adding a product to the cart.
This of course will not work with product variations, but if you know the product ID, do something like this:

In your custom module, implement hook_menu().

function hook_menu(){
  return array(
    'custom/add-to-cart/%commerce_product' => array(
      'type' => MENU_CALLBACK,
      'page callback' => 'custom_add_to_cart',
      'page arguments' => array(2),
      'access callback' => TRUE,
    ),
  );
}

Create your callback function:

function custom_add_to_cart($product) {
  global $user;
  $uid = $user->uid;

  // Get the order to add line items to.
  $order = commerce_cart_order_load($uid);

  if (!$order) {
    $order = commerce_cart_order_new($uid);
  }

  // Add the product to the line item and create it.
  $line_item = commerce_product_line_item_new($product, $quantity = 1, $order->order_id, array(), $line_item_type = 'product');

  // Add the line item to the cart.
  if(commerce_cart_product_add($uid, $line_item)) {
    drupal_goto('cart');
  }

Now you can create your own add to cart link in a View that points to custom/add-to-cart/PRODUCT_ID.

donutdan4114’s picture

Title: On AJAX-enabled views the "Add to cart" button do not working » On AJAX-Enabled Views the "Add to Cart" button does not work
Issue summary: View changes
rszrama’s picture

You could also use https://drupal.org/project/rules_link and manage it via Rules.

pixelula’s picture

This was my workaround:

function hook_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'commerce_cart_add_to_cart') !== FALSE) {
    $query = drupal_http_build_query(drupal_get_query_parameters());
    $form['#action'] = base_path() . current_path() . '?' . $query;
  }
}
mstevetodd’s picture

For the benefit of others finding this page, my problem turned out to be that I had HTML caching enabled on the view. See this: https://www.drupal.org/node/1926888

Vilgo’s picture

#6 works like a charm. Thank you Pixelula.

andyg8’s picture

Thanks mstevetodd for pointing out the caching issue. That was causing our site's Add to cart button to fail if used on a 2nd product in a view (even a non-Ajax view). We found we could still cache if we used Views, caching > time based > cache raw query results (1 hour) but NOT cache rendered output.

joro78’s picture

Confirming that #6 works.

Just remember to change the name of the function,
matching your theme name (for ex. function mytheme_form_alter...),
and put it in template.php file.

Thanks also from me pixelula =)

I just want to inform that there might be a problem with multilingual sites.
A solution is to get the language prefix and add it after the base path in order not to switch to default
after adding the product into cart. My code in template.php looks like this:

function mytheme_form_alter(&$form, &$form_state, $form_id) {

global $language;
$curlang = $language->language;

if (strpos($form_id, 'commerce_cart_add_to_cart') !== FALSE) {
$query = drupal_http_build_query(drupal_get_query_parameters());
$form['#action'] = base_path() . ($curlang) . ('/') . current_path() . '?' . $query;
}
}

Discussion and solution concerning similar issue is found here:
https://drupal.stackexchange.com/questions/129819/print-current-base-lan...

ddhuri’s picture

#6 works for me, Thank you pixelula.

chandrahas.d’s picture

Hello guys,

I am facing the same issue in Drupal 8 and I am not able to find any solution.
I tried to convert the same Drupal 7 code to Drupal 8 but i am not able to make it work.
Any ideas or pointers would be useful.

Thanks.

Lovejit_singh’s picture

#6 works well for me, though it returns only the next page products after product added to cart.

I found this solution for that.


if (strpos($form_id, 'commerce_cart_add_to_cart') !== FALSE) {
        //Fixing Json Error on AJAX
        $query = drupal_http_build_query(drupal_get_query_parameters());
        $form['#action'] = base_path() . current_path() . '?' . $query;
        $form['#submit'][] = '_custom_cart_submit';
    }


function _custom_cart_submit($form, &$form_state) {
    $form_state['redirect'] = url(current_path(), array('absolute' => true));
}