Question

I am trying to update cart without refreshing when someone clicks on-increment or decrement button by creating custom module.

I override the cart/item/default.xml and add button, script to send formkey & qty of the updated cart to updateItemQty controller, I am trying to achieve the same functionality of update shopping cart button with my increment/decrement button

Here is File path which I override:

Module-checkout/view/frontend/templates/cart/item/default.phtml

File: default.xml

<label for="cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty">
                <span class="label"><?= $block->escapeHtml(__('Qty')) ?></span>
                <button type="button" id="increaseQty">+</button>
                <input id="cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty"
                       name="cart[<?= $block->escapeHtmlAttr($_item->getId()) ?>][qty]"
                       data-cart-item-id="<?= $block->escapeHtmlAttr($_item->getSku()) ?>"
                       value="<?= $block->escapeHtmlAttr($block->getQty()) ?>"
                       type="number"
                       size="4"
                       title="<?= $block->escapeHtmlAttr(__('Qty')) ?>"
                       class="input-text qty"
                       data-validate="{required:true,'validate-greater-than-zero':true}"
                       data-role="cart-item-qty"/>
                <button type="button" id="decreaseQty">-</button>
                <input name="form_key" id="form_key" type="hidden" value="<?php echo $block->getFormKey();?>">
</label>

and here is the script:

<?php
   //-- form key load
   echo $this->getBlockHtml('formkey');
?>
<?php echo $this->getBlockHtml('formkey'); ?>
<script type="text/javascript">
  require(["jquery"],function($){
      var formKey = jQuery("[name='form_key']").val();
      $("#increaseQty").on("click",function(){
        var currentQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
        var newAdd = parseInt(currentQty)+parseInt(1);
        $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val(newAdd);
        var updateQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
        var url = "<?php echo $block->getBaseUrl().'checkout/cart/updateItemQty' ?>";
        $.ajax({
            url: url,
            method: "POST",
            data: { form_key:formKey,"cart[<?= $block->escapeHtmlAttr($_item->getId()) ?>][qty]": updateQty},
            dataType: 'json',
            showLoader:true,
            cache: false,
            success: function(data){
            }
        });

    });
});

currently I just added a script for increment button, I check that its send data perfectly to updateItemQtycontroller similar to update shopping cart button (formkey + qty) but it's not sending data to updatePost controller.

What did I do wrong??

Was it helpful?

Solution

First, change the button from static id to dynamic id, so it will work if cart have more than one product.

File: default.xml

<button type="button" id="increaseQty-<?= $block->escapeHtmlAttr($_item->getId()) ?>-btn">+</button>

<button type="button" id="decreaseQty-<?= $block->escapeHtmlAttr($_item->getId()) ?>-btn">-</button>

And this is the script:

<script type="text/javascript">
require(["jquery",
    "Magento_Checkout/js/model/quote",
    "Magento_Checkout/js/model/cart/totals-processor/default"
    ],
    function($, quote, totalsDefaultProvider){
        var formKey = jQuery("[name='form_key']").val();
        $("#increaseQty-<?= $block->escapeHtmlAttr($_item->getId()) ?>-btn").on("click",function(){
            var currentQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
            var newAdd = parseInt(currentQty)+parseInt(1);
            $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val(newAdd);
            var updateQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
            var url = "<?php echo $block->getBaseUrl().'checkout/cart/updatePost' ?>";
            $.ajax({
                url: url,
                method: "POST",
                data: { form_key:formKey,"cart[<?= $block->escapeHtmlAttr($_item->getId()) ?>][qty]": updateQty},
                dataType: 'json',
                showLoader:true,
                cache: false,
                success: function(data){
                }
            });
        });
        $("#decreaseQty-<?= $block->escapeHtmlAttr($_item->getId()) ?>-btn").on("click",function(){
            var currentQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
            if(currentQty>1){
                var newAdd = parseInt(currentQty)-parseInt(1);
                $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val(newAdd);
                var updateQty = $("#cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty").val();
            }else{
                alert("Can not choose less than one");exit();
            }
            var url = "<?php echo $block->getBaseUrl().'checkout/cart/updatePost' ?>";
            $.ajax({
                url: url,
                method: "POST",
                data: { form_key:formKey,"cart[<?= $block->escapeHtmlAttr($_item->getId()) ?>][qty]": updateQty},
                dataType: 'json',
                showLoader:true,
                cache: false,
                success: function(data){
                }
            });
        });
    });
</script>

OTHER TIPS

Step 1:

In your custom them create Magento_Theme/layout/checkout_cart_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
    <referenceContainer name="content">
        <block class="Magento\Framework\View\Element\Template" name="cart.ajax.qty.update"  template="Magento_Theme::js.phtml" after="-"/>
    </referenceContainer>
</body>

Step 2:

Create js.phtml file Magento_Theme/templates/js.phtml

<script>
require ([
        'jquery',
    ],
    function ($) {
       $(window).on("load", function () {
            require([
                'custom'
            ]);
        });
    });

Step 3:

Create custom.js file in theme web folder Namespace/Yourtheme/web/js/custom.js

    define([
    'jquery',
    'Magento_Checkout/js/action/get-totals',
    'Magento_Customer/js/customer-data'
     ], function ($, getTotalsAction, customerData) {

    $(document).ready(function(){
    $(document).on('change', 'input[name$="[qty]"]', function(){
        var form = $('form#form-validate');
        $.ajax({
            url: form.attr('action'),
            data: form.serialize(),
            showLoader: true,
            success: function (res) {
                var parsedResponse = $.parseHTML(res);
                var result = $(parsedResponse).find("#form-validate");
                var sections = ['cart'];

                $("#form-validate").replaceWith(result);

                // The mini cart reloading
                customerData.reload(sections, true);

                // The totals summary block reloading
                var deferred = $.Deferred();
                getTotalsAction([], deferred);
            },
            error: function (xhr, status, error) {
                var err = eval("(" + xhr.responseText + ")");
                console.log(err.Message);
            }
        });
       });
      });
    });

Step 4:

(map your js file) Create requirejs-config.js on your theme root Namespace/yourtheme/requirejs-config.js

var config = {
   map: {
    '*': {
        custom:'Magento_Theme/js/custom'
    }
  }
};

Now the qty update work using ajax.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top