Cart page update with AJAX using increment/decrements button
-
24-03-2021 - |
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 updateItemQty
controller similar to update shopping cart
button (formkey + qty) but it's not sending data to updatePost
controller.
What did I do wrong??
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.