I use latest version of WordPress and Woocommerce. I have some JavaScript that loops over DOM elements of class .selectable
and grabs the product_id
attribute from the ones with class .selected
, and adds that item to the cart:
// selects the elements
$('.next').on('click', function() {
var parent = $(this).closest('.panel');
var selectables = parent.children('.option.selectable.selected');
$(selectables).each(function() {
var product = $(this).attr('product');
add_to_cart(product, 1);
});
}
// add to cart AJAX
function add_to_cart(product_id, qty) {
$.ajax({
type: "POST",
url: base_url + '/wp-admin/admin-ajax.php',
data: {action : 'cl_add_to_cart', 'product_id': product_id, 'qty': qty},
success : function(response) {
console.log(response);
}
});
}
And I have a PHP function in functions.php
add_action('wp_ajax_cl_add_to_cart', 'cl_add_to_cart');
add_action('wp_ajax_nopriv_cl_add_to_cart', 'cl_add_to_cart');
function cl_add_to_cart() {
global $woocommerce;
$product_id = trim($_POST['product_id']);
$qty = !empty($_POST['qty']) ? trim($_POST['qty']) : 1;
$added = WC()->cart->add_to_cart($product_id, $qty);
echo json_encode($added);
}
The AJAX call is hitting the PHP function just fine – I can echo out $added which gives me a hash. If I have two or more items in the selectables var, they both hit the PHP function (I get two hashes back) but only the first one gets added to the cart.
I can’t for the life of me figure out why. Any ideas?
2
Answers
Is better to send all items to be added all together at once with Ajax, than send them separately in multiple Ajax requests, this will be lighter and more effective.
You need to be sure that
$(selectables).each(function() { // ... });
is working as you expect.The following will send a unique Ajax request for your click event.
The jQuery code
The php receiver function:
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
It should work adding all items at once.
The main answer does not really address the underlying problem. Plus it is not always possible to add the products at the same time. You may have an order form where the user can click quickly on multiple different items.
Here’s the problem:
The WooCommerce add to cart function works by setting the
$this->cart_contents
variable to specific items.The problem occurs when you use
WC()->cart->add_to_cart()
in AJAX, because multiple such add_to_cart functions are running concurrently. What happens is that one function will start after the previous function started but did not finish.The result is that the 2nd function sets the cart content, without knowing it’s missing the products the previous function just added.
Now the solution: Make the javascript wait until the previous function finished with a recursive function:
(this code is not complete, it just illustrates the idea):