Magento 2.2 – How to Reload Shopping Cart Summary via Ajax

magento-2.1magento2magento2.2magento2.2.4

I am adding quantity increment/decrement buttons on shopping cart page. How can I reload cart summery (subtotal/shipping rate/grand total/discount/tax section) via ajax ?

enter image description here

I have added below code in app/degign/frontend/Theme Vendor/Theme/Magento_checkout/templates/cart/item/default.phtml to add +/- buttons

<div class="control qty">
    <button type="button"   id="<?= /* @escapeNotVerified */ $_item->getId() ?>-dec"  class="decreaseQty"></button>
    <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"
           name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]"
           data-cart-item-id="<?= /* @escapeNotVerified */ $_item->getSku() ?>"
           value="<?= /* @escapeNotVerified */ $block->getQty() ?>"
           type="number"
           size="4"
           title="<?= $block->escapeHtml(__('Qty')) ?>"
           class="input-text qty"
           data-validate="{required:true,'validate-greater-than-zero':true}"
           data-role="cart-item-qty"/>
    <button type="button"  id="<?= /* @escapeNotVerified */ $_item->getId() ?>-upt" class="increaseQty"></button>
</div>

And added below javascript in cart.phtml

<script>
require([
    'jquery', 
    'Magento_Customer/js/customer-data',
    'jquery/jquery-storageapi',
    'Magento_Checkout/js/action/get-totals'

    ], function ($, customerData, storageApi, getTotalsAction) {
    // $("#submitbutton").hide();
    var form = $('form#form-validate');
    var qtyfields = $('input.qty');
    $('.page.messages').each(function () {
        var thismessage = $(this);
        thismessage.attr('id', 'messages');
    });

    form.find(qtyfields).each(function (e) {
        var thisfield = $(this);
        $(this).change(function () {
            console.log('change detected');
            form.submit();
        });

    });
    form.on('submit', function (e) {
        e.preventDefault();
        $.ajax({
            url: form.attr('action'),
            data: form.serialize(),
            type: 'post',
            success: function (res) {

                //code to reload cart item section
                var parsedResponse = $.parseHTML(res);
                var result = $(parsedResponse).find("#form-validate");
                $("#form-validate").replaceWith(result);

                //below two lines refershing cart summary
                var deferred = $.Deferred();
                getTotalsAction([], deferred);

            },
            error: function () {
                console.log('error');
            }
        });
        console.log('form submitted');
    });
});
</script>

But cart summary is not reloading after quantity change.

Best Answer

Finally I got the solution.

I have added below code in app/degign/frontend/Theme Vendor/Theme/Magento_checkout/templates/cart/item/default.phtml to add +/- buttons

<div class="control qty">
    <button type="button"   id="<?= /* @escapeNotVerified */ $_item->getId() ?>-dec"  class="decreaseQty"></button>
    <input id="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty"
           name="cart[<?= /* @escapeNotVerified */ $_item->getId() ?>][qty]"
           data-cart-item-id="<?= /* @escapeNotVerified */ $_item->getSku() ?>"
           value="<?= /* @escapeNotVerified */ $block->getQty() ?>"
           type="number"
           size="4"
           title="<?= $block->escapeHtml(__('Qty')) ?>"
           class="input-text qty"
           data-validate="{required:true,'validate-greater-than-zero':true}"
           data-role="cart-item-qty"/>
    <button type="button"  id="<?= /* @escapeNotVerified */ $_item->getId() ?>-upt" class="increaseQty"></button>
</div>

Then I overrides shopping-cart.js to app/design/frontend/Theme Vendor/Theme/Magento_Checkout/web/js/shopping-cart.js and added my javascript code there.

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define([
    'jquery',
    'jquery/ui',
    'Magento_Checkout/js/action/get-totals' //additionally added
], function ($, jQueryUi, getTotalsAction) {
    'use strict';

    //code to update quantity starts
    $(document).ready(function(){
        $('.increaseQty, .decreaseQty').on("click",function(){ 
            var $this = $(this);
            var ctrl = ($(this).attr('id').replace('-upt','')).replace('-dec','');          
            var currentQty = $("#cart-"+ctrl+"-qty").val();
            if($this.hasClass('increaseQty')){
                var newAdd = parseInt(currentQty)+parseInt(1);
                 $("#cart-"+ctrl+"-qty").val(newAdd);
                 $('input.qty').trigger('change');
            }else{
                 if(currentQty>1){
                    var newAdd = parseInt(currentQty)-parseInt(1);
                    $("#cart-"+ctrl+"-qty").val(newAdd);
                    $('input.qty').trigger('change');
                 }
            }
        });

        var form = $('form#form-validate');
        var qtyfields = $('input.qty');
        $('.page.messages').each(function () {
            var thismessage = $(this);
            thismessage.attr('id', 'messages');
        });

        form.find(qtyfields).each(function (e) {
            var thisfield = $(this);
            $(this).change(function () {
                console.log('change detected');
                form.submit();
            });

        });
        form.on('submit', function (e) {
            e.preventDefault();
            $.ajax({
                url: form.attr('action'),
                data: form.serialize(),
                type: 'post',
                success: function (res) {
                    var parsedResponse = $.parseHTML(res);
                    var result = $(parsedResponse).find("#form-validate");
                    $("#form-validate").replaceWith(result);

                    var deferred = $.Deferred();
                    getTotalsAction([], deferred);

                },
                error: function () {
                    console.log('error');
                }
            });
            console.log('form submitted');
        });
    });
    //code to update quantity ends

    $.widget('mage.shoppingCart', {
        /** @inheritdoc */
        _create: function () {
            var items, i;

            $(this.options.emptyCartButton).on('click', $.proxy(function () {
                $(this.options.emptyCartButton).attr('name', 'update_cart_action_temp');
                $(this.options.updateCartActionContainer)
                    .attr('name', 'update_cart_action').attr('value', 'empty_cart');
            }, this));
            items = $.find('[data-role="cart-item-qty"]');

            for (i = 0; i < items.length; i++) {
                $(items[i]).on('keypress', $.proxy(function (event) { //eslint-disable-line no-loop-func
                    var keyCode = event.keyCode ? event.keyCode : event.which;

                    if (keyCode == 13) { //eslint-disable-line eqeqeq
                        $(this.options.emptyCartButton).attr('name', 'update_cart_action_temp');
                        $(this.options.updateCartActionContainer)
                            .attr('name', 'update_cart_action').attr('value', 'update_qty');

                    }
                }, this));
            }
            $(this.options.continueShoppingButton).on('click', $.proxy(function () {
                location.href = this.options.continueShoppingUrl;
            }, this));
        }
    });

    return $.mage.shoppingCart;
});

Hope this will help others :)