1/12/16

WooCommerce Add to Cart with Ajax on Single Product Page

jax is fun. Most people prefer Ajax so that there is loading of pages involved and the user can see everything right in front of them without refreshing or redirecting to another page.

I will explain you step by step how you can add a product from your single product page with Ajax in WooCommerce. This a lengthy article so make sure you have some coffee with you.

Adding Cart Icon in the header

The first step is to add an icon in the header which will show your cart contents after the Ajax updates the cart.

You can pick up any image of a basket/cart or any font-awesome icon to display this. You can also display the cart count, that is the number of products currently in the cart and also show the amount.

Here is the code to show the cart items count and total in the header
<div class="cart-header">
<a class="cart-contents" href="<?php echo wc_get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>">
<span class="icon icon-basket"></span>
<span class="cart-count-total"><!--?php echo sprintf ( _n( '%d', '%d', WC()--->cart->get_cart_contents_count() ), WC()->cart->get_cart_contents_count() ); ?></span>
</a>
</div>
 The icon-basket class can be used to display an icon from font-awesome or if you want to display an image there.

The cart-count-total class will contain the number of items that the user has in his/her shopping cart.

Add the necessary CSS to those classes the way you want them to look. I have used this on a theme so this is how it looks after adding that code.


We also need a drop down here for the cart items to show up so let’s add the drop down div to the code.
<div class="cart-header">
<a class="cart-contents" href="<?php echo wc_get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>">
<span class="icon icon-basket"></span>
<span class="cart-count-total"><!--?php echo sprintf ( _n( '%d', '%d', WC()--->cart->get_cart_contents_count() ), WC()->cart->get_cart_contents_count() ); ?></span>
</a>

<div class="cart-dropdown">
<div class="cart-dropdown-inner">
<h4>Shopping Bag</h4>
</div>
</div>
</div>
We will also want to display the existing cart items here so we use the following code to display that along with the cart and checkout links

<div class="cart-header">
<a class="cart-contents" href="<?php echo wc_get_cart_url(); ?>" title="<?php _e( 'View your shopping cart' ); ?>">
<span class="icon icon-basket"></span>
<span class="cart-count-total"><!--?php echo sprintf ( _n( '%d', '%d', WC()--->cart->get_cart_contents_count() ), WC()->cart->get_cart_contents_count() ); ?></span>
</a>

<div class="cart-dropdown">
<div class="cart-dropdown-inner">
<!--?php $items = WC()--->cart->get_cart();

if ($items) { ?>
<h4>Shopping Bag</h4>

<!--?php foreach($items as $item =--> $values) { 
$_product = $values['data']->post; ?>
<div class="dropdown-cart-wrap">
<div class="dropdown-cart-left">
<!--?php echo get_the_post_thumbnail( $values['product_id'], 'thumbnail' ); ?-->
</div>

<div class="dropdown-cart-right">
<h5><!--?php echo $_product--->post_title; ?></h5>
<p>Quantity: <!--?php echo $values['quantity']; ?--></p>
<p>Price: £ <!--?php echo get_post_meta($values['product_id'] , '_price', true); ?--></p>
</div>

<div class="clear"></div>
</div>
<!--?php } ?-->

<div class="dropdown-cart-wrap">
<div class="dropdown-cart-left">
<h6>Subtotal</h6>
</div>

<div class="dropdown-cart-right">
<h6><!--?php echo WC()--->cart->get_cart_total(); ?></h6>
</div>

<div class="clear"></div>
</div>

<div class="dropdown-cart-wrap dropdown-cart-last">
<div class="dropdown-cart-left dropdown-cart-link">
<a href="/cart/">View Basket</a>
</div>

<div class="dropdown-cart-right dropdown-checkout-link">
<a href="/checkout/">Checkout</a>
</div>

<div class="clear"></div>
</div>
<!--?php } else { ?-->
<h4>Shopping Bag</h4>

<div class="dropdown-cart-wrap">
<p>Your cart is empty.</p>
</div>

<div class="dropdown-cart-wrap">
<div class="dropdown-cart-left">
<h6>Subtotal</h6>
</div>

<div class="dropdown-cart-right">
<h6><!--?php echo WC()--->cart->get_cart_total(); ?></h6>
</div>

<div class="clear"></div>
</div>

<div class="dropdown-cart-wrap dropdown-cart-last">
<div class="dropdown-cart-left dropdown-cart-link">
<a href="/cart/">View Basket</a>
</div>

<div class="dropdown-cart-right dropdown-checkout-link">
<a href="/checkout/">Checkout</a>
</div>

<div class="clear"></div>
</div>
<!--?php } ?-->
</div>
</div>
</div>
After adding the above code, add the CSS that you want to add to style this dropdown. This is how the drop down looks on the theme that I am creating this on.


Now that the header is ready. Let’s begin the WooCommerce part.

Adding JS to the WooCommerce Add to Cart Button on Single Product page

By default if the user clicks on the add to cart button on the single product pages, that item is added to the cart and then a message is displayed below the header which says that the item has been added to the cart.

So let’s disable that altogether and create our own Ajax for that button

Place the following code in your JS file of your theme. If you don’t have one (which is very unlikely to happen) or if you are using a child theme, use wp_enqueue_script() to add a JS file to your theme. Also use wp_localize_script to get the admin-ajax.php URL in your Ajax call.

jQuery(document).ready(function($) {
$(".single_add_to_cart_button").click(function(e) {
e.preventDefault();

console.log('clicked');
});
});
The above code will basically disable the add to cart button on the single product page to function and just to test it will send a “clicked” text to the developer console of your browser. After adding the above code, if you head over to any single product page, you will see a message in your console, something like this..


jQuery(document).ready(function($) {
$(".single_add_to_cart_button").click(function(e) {
e.preventDefault();

var product_id = $('input[name="add-to-cart"]').val();
var quantity = $('input[name="quantity"]').val();
$('.cart-dropdown-inner').empty();

$.ajax ({
                    url: my_ajax_object.ajax_url,
                    type:'POST',
                    data:'action=my_wc_add_cart&product_id=' + product_id + '&quantity=1',

                    success:function(results) {
                        $('.cart-dropdown-inner').html(results);
                    }
               });
       });
});
If you have simple as well as variable products on your website, then use the following code.

jQuery(document).ready(function($) {
$(".single_add_to_cart_button").click(function(e) {
e.preventDefault();

var product_id = $('input[name="add-to-cart"]').val();
var variation_id = $('input[name="variation_id"]').val();
var quantity = $('input[name="quantity"]').val();
$('.cart-dropdown-inner').empty();

if (variation_id != '') {
$.ajax ({
                   url: my_ajax_object.ajax_url,
                   type:'POST',
                   data:'action=my_wc_add_cart&product_id=' + product_id + '&variation_id=' + variation_id + '&quantity=' + quantity,

                   success:function(results) {
                        $('.cart-dropdown-inner').append(results);
                   }
              });
} else {
$.ajax ({
                   url: my_ajax_object.ajax_url,  
                   type:'POST',
                   data:'action=my_wc_add_cart&product_id=' + product_id + '&quantity=' + quantity,

                   success:function(results) {
                       $('.cart-dropdown-inner').append(results);
                   }
       });
 }
    });
});
The product_id will pull in the ID of the product. quantity will get the quantity selected by the user. variation_id gets the variation ID of the item that is added to the cart. We also run a conditional tag on ‘variation_id’ so that we can pass the variation ID to the Ajax function. ‘.empty()’ is used to empty the contents of the drop down so that we can update it with new content. The ‘my_wc_add_cart’ is the function which will add the product to the cart and then send back the cart contents to update the drop down in the header.

The PHP side

Every theme should have a functions.php file. If you are using a child theme, then use the functions.php of the child theme and paste the following code there.

function my_wc_add_cart_ajax() {
$product_id = $_POST['product_id'];
$variation_id = $_POST['variation_id'];
$quantity = $_POST['quantity'];

if ($variation_id) {
WC()->cart->add_to_cart( $product_id, $quantity, $variation_id );
} else {
WC()->cart->add_to_cart( $product_id, $quantity);
}

$items = WC()->cart->get_cart(); ?>

<h4>Shopping Bag</h4>

<!--?php foreach($items as $item =--> $values) { 
$_product = $values['data']->post; ?>

<div class="dropdown-cart-wrap">
<div class="dropdown-cart-left">
<!--?php echo get_the_post_thumbnail( $values['product_id'], 'thumbnail' ); ?-->
</div>

<div class="dropdown-cart-right">
<h5><!--?php echo $_product--->post_title; ?></h5>
<p>Quantity: <!--?php echo $values['quantity']; ?--></p>
<p>Price: £ <!--?php echo get_post_meta($values['product_id'] , '_price', true); ?--></p>
</div>

<div class="clear"></div>
</div>
<!--?php } ?-->

<div class="dropdown-cart-wrap">
<div class="dropdown-cart-left">
<h6>Subtotal</h6>
</div>

<div class="dropdown-cart-right">
<h6><!--?php echo WC()--->cart->get_cart_total(); ?></h6>
</div>

<div class="clear"></div>
</div>

<div class="dropdown-cart-wrap dropdown-cart-last">
<div class="dropdown-cart-left dropdown-cart-link">
<a href="/cart/">View Basket</a>
</div>

<div class="dropdown-cart-right dropdown-checkout-link">
<a href="/checkout/">Checkout</a>
</div>

<div class="clear"></div>
</div>

<!--?php die();
}

add_action('wp_ajax_my_wc_add_cart', 'my_wc_add_cart_ajax');
add_action('wp_ajax_nopriv_my_wc_add_cart', 'my_wc_add_cart_ajax'); ?-->
We fire the ‘my_wc_add_cart’ function in the functions.php file which first pulls the item which was sent to it from the Ajax function. We then add the product to the cart along with the quantity and the variation which was added. Then we use the WC()->cart->get_cart() function to get the items in the cart and then create the HTML markup for the cart drop down. The above function will return the product image, title, quantity and the price of the products in the cart. In addition to that, it will also show the Subtotal (since total price is calculated after entering the shipping details) and the WooCommerce cart and checkout page links.

This is how my cart drop down looks after I added the CSS for that particular site.


Additionally, a spinner/loader can be added to the “Add to Cart” button and also the drop down can be displayed for a few seconds to show the user that the item has been added to the cart.

I have also displayed the attribute name which was added to the cart by the user. If you want to display that, use the following function to overwrite the item details function with this.

<div class="dropdown-cart-right">
<h5><!--?php echo $_product--->post_title; ?></h5>
<p>Quantity: <!--?php echo $values['quantity']; ?--></p>
<!--?php if($values['variation_id']) { ?-->
<p>Size: <!--?php $variation = wc_get_product($values['variation_id']);
$varname = $variation--->get_formatted_name();
preg_match('/(?<=size: )\S+/i', $varname, $match);
echo $match[0]; ?></p>
<!--?php } ?-->
<p>Price: £ <!--?php echo get_post_meta($values['product_id'] , '_price', true); ?--></p>
</div>
Feel free to comment or ask anything you want.

1 nhận xét: