WooCommerce - change QTY triggers AJAX call in cart
Asked Answered
Q

3

8

I would like to update and then reload my cart via AJAX when the quantity of an item in the cart is changed.

I can already successfully load in my cart via AJAX.

To load in my cart my php function looks like this. (in my functions.php)

function enqueue_cart_show_ajax() {

    wp_register_script( 'cart-show-ajax-js', get_template_directory_uri() . '/js/cart-show-ajax.js', array( 'jquery' ), '', true );
    wp_localize_script( 'cart-show-ajax-js', 'cart_show_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
    wp_enqueue_script( 'cart-show-ajax-js' );

}
add_action('wp_enqueue_scripts', 'enqueue_cart_show_ajax');

function ajax_show_cart() {

    echo do_shortcode( '[woocommerce_cart]' );

    die();

}

add_action('wp_ajax_show_cart', 'ajax_show_cart');
add_action('wp_ajax_nopriv_show_cart', 'ajax_show_cart');

My Jquery code looks like this (in cart-show-ajax.js)

jQuery(function($) {

    //If view-cart is clicked, fill the view-cart-popup window with the cart
    $( '.view-cart' ).on('click', function(){
        show_cart(); 
    });

    //Main ajax function
    function show_cart() {

        $.ajax({
            type: 'GET',
            url: cart_show_ajax.ajax_url,
            data: {
                action: 'show_cart',
            },
            beforeSend: function ()
            {
                //You could show a loader here
            },
            success: function(data)
            {
                //Hide loader here
                $( '.view-cart-popup' ).html(data);
                activateReturnToShop();
            },
            error: function()
           {
                //If an ajax error has occured, do something here...
                $(".product-container").html('<p>There has been an error</p>');
            }
        });

    }

});

The HTML for the cart is as follows

<td class="product-quantity">
    <div class="quantity">
        <input type="number" step="1" min="0"
         name="cart[1e334311e1ef4cf849abff19e4237358][qty]"
         value="4" title="Qty" class="input-text qty text" size="4">
    </div>
</td>

My best guess is that I can achieve this if when the input is changed I run a function that updates the cart, then simply runs the existing show_cart() function.

I'm not sure about how to make a function that will detect the change to input, grab the new quantity of the product and update the amount in the cart...

It could looks something like:

$( 'input.qty' ).on("change", function(){
    // Grab the new product quantity
    // Update the cart
    show_cart();
});

Anyone know how to get the new quantity update the cart with it?

Thank you for all your help!

Quiberon answered 25/8, 2015 at 5:25 Comment(0)
Q
15

Okay so I figured it out! I can now update cart item's quantities without refreshing via AJAX (:

my functions.php looks like this

//Enqueue Ajax Scripts
function enqueue_cart_qty_ajax() {

    wp_register_script( 'cart-qty-ajax-js', get_template_directory_uri() . '/js/cart-qty-ajax.js', array( 'jquery' ), '', true );
    wp_localize_script( 'cart-qty-ajax-js', 'cart_qty_ajax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
    wp_enqueue_script( 'cart-qty-ajax-js' );

}
add_action('wp_enqueue_scripts', 'enqueue_cart_qty_ajax');

function ajax_qty_cart() {

    // Set item key as the hash found in input.qty's name
    $cart_item_key = $_POST['hash'];

    // Get the array of values owned by the product we're updating
    $threeball_product_values = WC()->cart->get_cart_item( $cart_item_key );

    // Get the quantity of the item in the cart
    $threeball_product_quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );

    // Update cart validation
    $passed_validation  = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $threeball_product_values, $threeball_product_quantity );

    // Update the quantity of the item in the cart
    if ( $passed_validation ) {
        WC()->cart->set_quantity( $cart_item_key, $threeball_product_quantity, true );
    }

    // Refresh the page
    echo do_shortcode( '[woocommerce_cart]' );

    die();

}

add_action('wp_ajax_qty_cart', 'ajax_qty_cart');
add_action('wp_ajax_nopriv_qty_cart', 'ajax_qty_cart');

My cart-qty-ajax.js looks like this.

jQuery( function( $ ) {

    $( document ).on( 'change', 'input.qty', function() {

        var item_hash = $( this ).attr( 'name' ).replace(/cart\[([\w]+)\]\[qty\]/g, "$1");
        var item_quantity = $( this ).val();
        var currentVal = parseFloat(item_quantity);

        function qty_cart() {

            $.ajax({
                type: 'POST',
                url: cart_qty_ajax.ajax_url,
                data: {
                    action: 'qty_cart',
                    hash: item_hash,
                    quantity: currentVal
                },
                success: function(data) {
                    $( '.view-cart-popup' ).html(data);
                }
            });  

        }

        qty_cart();

    });

});

Works beautifully, though I'm not sure if this is 'good practice'. Thanks all!

Quiberon answered 29/8, 2015 at 14:26 Comment(3)
Is this possible on the checkout page as well? On the checkout page, customers are allowed to change quantity.Yeomanry
why preg_replace && filter_var? extra safety somehow?Walachia
You should be updating the cart fragments instead of running a shortcode.Damalis
D
5

This is a easy ways to resolve this if your are doing the scripting your selves instead of any plugin. Below code will help you to update the cart on quantity dropdown change in customize pop up window where mini cart is displaying: javascript:

$(document).on('click', '.qty', function (e)
    {
     e.preventDefault();
     var qty = $(this).val();
     var cart_item_key = $(this).attr("id");

   $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '<?php echo SITE_URL; ?>/wp-admin/admin-ajax.php',
        data: {action : 'update_item_from_cart', 'cart_item_key' : cart_item_key, 'qty' : qty,  },
        success: function (data) {
           alert('Updated successfully.');
        if (data) {
            alert('You missed something');
        }else{
            alert('Updated Successfully');
        }
    }

    });

 });

*In above script .qty is class of the number dropdown. *Pass two values only i.e cart_item_key and quantity. *SITE_URL is domain name *pass two values i.e. qty and cart item key

in functions.php place the below script

function update_item_from_cart() {
     $cart_item_key = $_POST['cart_item_key'];   
     $quantity = $_POST['qty'];     

    // Get mini cart
    ob_start();

    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item)
    {
        if( $cart_item_key == $_POST['cart_item_key'] )
        {
            WC()->cart->set_quantity( $cart_item_key, $quantity, $refresh_totals = true );
        }
    }
    WC()->cart->calculate_totals();
    WC()->cart->maybe_set_cart_cookies();
    return true;
}

add_action('wp_ajax_update_item_from_cart', 'update_item_from_cart');
add_action('wp_ajax_nopriv_update_item_from_cart', 'update_item_from_cart');
Discordant answered 25/6, 2018 at 2:19 Comment(0)
M
0
success: function(data) {
                $( '.view-cart-popup' ).html(data);

} //below function worked, not above

success: function(data) {

data = data.replace(///\s*</div>/g, '');

data = data.replace(///\s*</div>/g, '');

$('.woocommerce').replaceWith(data);

}

Mancunian answered 2/5 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.