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?
11 Answer
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
// Multi Ajax adda to cart function multiAddToCart( productsData ) { $.ajax({ url: base_url + '/wp-admin/admin-ajax.php', type: 'POST', dataType: 'JSON', data: { 'action': 'multi_add_to_cart', 'items' : Object.assign({}, productsData) }, success : function(response) { $(document.body).trigger('wc_fragment_refresh'); // Refresh cart fragments console.log(response); }, error : function(error) { console.log(error); } }); } $('.next').on('click', function() { var productsData = []; var parent = $(this).closest('.panel'); var selectables = parent.children('.option.selectable.selected'); $(selectables).each(function() { var productId = $(this).attr('product'); productsData.push({'id': productId, 'qty': 1}); }); // Check the data before (number of items found) console.log(productsData); multiAddToCart( productsData ); }); The php receiver function:
add_action('wp_ajax_multi_add_to_cart', 'multi_ajax_add_to_cart'); add_action('wp_ajax_nopriv_multi_add_to_cart', 'multi_ajax_add_to_cart'); function multi_ajax_add_to_cart() { if (isset($_POST['items']) ) { $item_keys = array(); foreach( $_POST['items'] as $item ) { if( isset($item['id']) ) { $item_qty = isset($item['qty']) && $item['qty'] > 1 ? $item['qty'] : 1; $item_keys[] = WC()->cart->add_to_cart($item['id'], $item_qty); } } echo json_encode($item_keys); // Send back cart item keys } die(); } 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.
1