In this post we wiil check how to Update Shopping Cart items quantity with AJAX on Checkout/cart and Checkout Page.
On checkout Page add + / - button on cart items and update qty with AJAX also update no. of items on cart summary by AJAX.
You can update checkout/cart items quantity seamlessly and see total price adjustments on the shopping cart page without having to click 'update to cart' button.
Display Alert before remove items from cart on Checkout/cart Page.
Let's start by creating custom module.
You can find complete module on Github at Magelearn_AjaxShoppingCartUpdate
Add registration.php file in it:
1 2 3 4 5 6 7 8 9 | <?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register( ComponentRegistrar::MODULE, 'Magelearn_AjaxShoppingCartUpdate' , __DIR__ ); |
Add composer.json file in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "name" : "magelearn/module-ajaxshoppingcartupdate" , "description" : "Update Shopping Cart items quantity with AJAX. You can update checkout/cart items quantity seamlessly and see total price adjustments on the shopping cart page without having to click 'update to cart' button." , "type" : "magento2-module" , "license" : "OSL-3.0" , "authors" : [ { "email" : "info@mage2gen.com" , "name" : "Mage2Gen" }, { "email" : "vijaymrami@gmail.com" , "name" : "vijay rami" } ], "minimum-stability" : "dev" , "autoload" : { "files" : [ "registration.php" ], "psr-4" : { "Magelearn\\AjaxShoppingCartUpdate\\" : "" } } } |
Add etc/module.xml file in it:
1 2 3 4 5 | <? xml version = "1.0" ?> < config xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation = "urn:magento:framework:Module/etc/module.xsd" > < module name = "Magelearn_AjaxShoppingCartUpdate" setup_version = "0.0.1" > </ module > </ config > |
Now first we will check how to add qty +/- button on checkout cart page and add alert when click on Remove item button on checkout/cart page.
FIrst add app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/layout/checkout_cart_index.xml file.
1 2 3 4 5 6 7 8 9 10 | <? xml version = "1.0" ?> < page xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" layout = "1column" xsi:noNamespaceSchemaLocation = "urn:magento:framework:View/Layout/etc/page_configuration.xsd" > < body > < referenceBlock name = "checkout.cart.form" > < action method = "setTemplate" > < argument name = "template" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/form.phtml</ argument > </ action > </ referenceBlock > </ body > </ page > |
Also add app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/layout/checkout_cart_item_renderers.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <? xml version = "1.0" ?> xsi:noNamespaceSchemaLocation = "urn:magento:framework:View/Layout/etc/page_configuration.xsd" > < body > <!-- override checkout cart item template --> < referenceBlock name = "checkout.cart.form" > < action method = "setOverriddenTemplates" > < argument xsi:type = "array" > <!-- list override templates --> < item name = "default" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "simple" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "configurable" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "bundle" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "downloadable" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "grouped" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > < item name = "virtual" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate::cart/item/default.phtml</ item > </ argument > </ action > </ referenceBlock > </ body > </ page > |
As per defined in above XML files we will add our phtml files and add code to update cart items with AJAX.
Copy file from vendor/magento/module-checkout/view/frontend/templates/cart/form.phtml and Add in app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/templates/cart/form.phtml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | <?php /** @var $block \Magento\Checkout\Block\Cart\Grid */ ?> <?php $mergedCells = ( $this ->helper(Magento\Tax\Helper\Data:: class )->displayCartBothPrices() ? 2 : 1); ?> <?= $block ->getChildHtml( 'form_before' ) ?> <form action= "<?= $block->escapeUrl($block->getUrl('checkout/cart/updatePost')) ?>" method= "post" id= "form-validate" data-mage-init='{ "Magento_Checkout/js/action/update-shopping-cart" : { "validationURL" : "<?= $block->escapeUrl($block->getUrl('checkout/cart/updateItemQty')) ?>" , "updateCartActionContainer" : "#update_cart_action_container" } }' class = "form form-cart" > <?= $block ->getBlockHtml( 'formkey' ) ?> <div class = "cart table-wrapper<?= $mergedCells == 2 ? ' detailed' : '' ?>" > <?php if ( $block ->getPagerHtml()): ?> <div class = "cart-products-toolbar cart-products-toolbar-top toolbar" data-attribute= "cart-products-toolbar-top" ><?= $block ->getPagerHtml() ?> </div> <?php endif ?> <table id= "shopping-cart-table" class = "cart items data table" data-mage-init='{ "shoppingCart" :{ "emptyCartButton" : ".action.clear" , "updateCartActionContainer" : "#update_cart_action_container" }}'> <caption class = "table-caption" ><?= $block ->escapeHtml(__( 'Shopping Cart Items' )) ?></caption> <thead> <tr> <th class = "col item" scope= "col" ><span><?= $block ->escapeHtml(__( 'Item' )) ?></span></th> <th class = "col price" scope= "col" ><span><?= $block ->escapeHtml(__( 'Price' )) ?></span></th> <th class = "col qty" scope= "col" ><span><?= $block ->escapeHtml(__( 'Qty' )) ?></span></th> <th class = "col subtotal" scope= "col" ><span><?= $block ->escapeHtml(__( 'Subtotal' )) ?></span></th> </tr> </thead> <?php foreach ( $block ->getItems() as $_item ): ?> <?= $block ->getItemHtml( $_item ) ?> <?php endforeach ?> </table> <?php if ( $block ->getPagerHtml()): ?> <div class = "cart-products-toolbar cart-products-toolbar-bottom toolbar" data-attribute= "cart-products-toolbar-bottom" ><?= $block ->getPagerHtml() ?> </div> <?php endif ?> </div> <div class = "cart main actions" > <?php if ( $block ->getContinueShoppingUrl()): ?> <a class = "action continue" href= "<?= $block->escapeUrl($block->getContinueShoppingUrl()) ?>" title= "<?= $block->escapeHtml(__('Continue Shopping')) ?>" > <span><?= $block ->escapeHtml(__( 'Continue Shopping' )) ?></span> </a> <?php endif ; ?> <?php if ( $block ->getViewModel()->isClearShoppingCartEnabled()): ?> <button type= "button" name= "update_cart_action" data-cart- empty = "" value= "empty_cart" title= "<?= $block->escapeHtml(__('Clear Shopping Cart')) ?>" class = "action clear" id= "empty_cart_button" > <span><?= $block ->escapeHtml(__( 'Clear Shopping Cart' )) ?></span> </button> <?php endif ?> <button type= "submit" name= "update_cart_action" data-cart-item-update= "" value= "update_qty" title= "<?= $block->escapeHtml(__('Update Shopping Cart')) ?>" class = "action update" > <span><?= $block ->escapeHtml(__( 'Update Shopping Cart' )) ?></span> </button> <input type= "hidden" value= "" id= "update_cart_action_container" data-cart-item-update= "" /> </div> </form> <?= $block ->getChildHtml( 'checkout.cart.order.actions' ) ?> <?= $block ->getChildHtml( 'shopping.cart.table.after' ) ?> <script type= "text/javascript" > require ([ 'jquery' , 'CartQtyUpdate' ], function ($) { }); </script> <script> require ([ 'jquery' , 'mage/translate' , 'Magento_Ui/js/modal/confirm' , "mage/template" , ], function ($, $t , confirm, mageTemplate) { $( '.action-delete' ).click( function (e) { e.stopPropagation(); var params11 = $(e.currentTarget).data( 'post' ); console.log(params11); confirm({ title: $t ( "Remove item cart" ), content: $t ( "Do you want remove this item of the cart?" ), modalClass: "classModal" , actions: { confirm: function () { var params = $(e.currentTarget).data( 'post' ); var formTemplate = '<form action="<%- data.action %>" method="post">' + '<% _.each(data.data, function(value, index) { %>' + '<input name="<%- index %>" value="<%- value %>">' + '<% }) %></form>' ; var formKeyInputSelector = 'input[name="form_key"]' ; var formKey = $(formKeyInputSelector).val(); if (formKey) { params.data.form_key = formKey; } $(mageTemplate(formTemplate, { data: params })).appendTo( 'body' ).hide().submit(); } } }); }) }); </script> |
Copy file from vendor/magento/module-checkout/view/frontend/templates/cart/item/default.phtml file and Add in app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/templates/cart/item/default.phtml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | <?php /** @var $block \Magento\Checkout\Block\Cart\Item\Renderer */ $_item = $block ->getItem(); $product = $_item ->getProduct(); $isVisibleProduct = $product ->isVisibleInSiteVisibility(); /** @var \Magento\Msrp\Helper\Data $helper */ $helper = $this ->helper(Magento\Msrp\Helper\Data:: class ); $canApplyMsrp = $helper ->isShowBeforeOrderConfirm( $product ) && $helper ->isMinimalPriceLessMsrp( $product ); ?> <tbody class = "cart item" > <tr class = "item-info" > <td data-th= "<?= $block->escapeHtml(__('Item')) ?>" class = "col item" > <?php if ( $block ->hasProductUrl()) :?> <a href= "<?= $block->escapeUrl($block->getProductUrl()) ?>" title= "<?= $block->escapeHtml($block->getProductName()) ?>" tabindex= "-1" class = "product-item-photo" > <?php else :?> <span class = "product-item-photo" > <?php endif ;?> <?= $block ->getImage( $block ->getProductForThumbnail(), 'cart_page_product_thumbnail' )->toHtml() ?> <?php if ( $block ->hasProductUrl()) :?> </a> <?php else :?> </span> <?php endif ; ?> <div class = "product-item-details" > <strong class = "product-item-name" > <?php if ( $block ->hasProductUrl()) :?> <a href= "<?= $block->escapeUrl($block->getProductUrl()) ?>" ><?= $block ->escapeHtml( $block ->getProductName()) ?></a> <?php else :?> <?= $block ->escapeHtml( $block ->getProductName()) ?> <?php endif ; ?> </strong> <?php if ( $_options = $block ->getOptionList()) :?> <dl class = "item-options" > <?php foreach ( $_options as $_option ) :?> <?php $_formatedOptionValue = $block ->getFormatedOptionValue( $_option ) ?> <dt><?= $block ->escapeHtml( $_option [ 'label' ]) ?></dt> <dd> <?php if (isset( $_formatedOptionValue [ 'full_view' ])) :?> <?= $block ->escapeHtml( $_formatedOptionValue [ 'full_view' ]) ?> <?php else :?> <?= $block ->escapeHtml( $_formatedOptionValue [ 'value' ], [ 'span' , 'a' ]) ?> <?php endif ; ?> </dd> <?php endforeach ; ?> </dl> <?php endif ;?> <?php if ( $messages = $block ->getMessages()) :?> <?php foreach ( $messages as $message ) :?> <div class = "cart item message <?= $block->escapeHtmlAttr($message['type']) ?>" > <div><?= $block ->escapeHtml( $message [ 'text' ]) ?></div> </div> <?php endforeach ; ?> <?php endif ; ?> <?php $addInfoBlock = $block ->getProductAdditionalInformationBlock(); ?> <?php if ( $addInfoBlock ) :?> <?= $addInfoBlock ->setItem( $_item )->toHtml() ?> <?php endif ;?> </div> </td> <?php if ( $canApplyMsrp ) :?> <td class = "col msrp" data-th= "<?= $block->escapeHtml(__('Price')) ?>" > <span class = "pricing msrp" > <span class = "msrp notice" ><?= $block ->escapeHtml(__( 'See price before order confirmation.' )) ?></span> <?php $helpLinkId = 'cart-msrp-help-' . $_item ->getId(); ?> <a href= "#" class = "action help map" id= "<?= ($block->escapeHtmlAttr($helpLinkId)) ?>" data-mage-init='{ "addToCart" :{ "helpLinkId" : "#<?= $block->escapeJs($block->escapeHtml($helpLinkId)) ?>" , "productName" : "<?= $block->escapeJs($block->escapeHtml($product->getName())) ?>" , "showAddToCart" : false } }' > <span><?= $block ->escapeHtml(__( "What's this?" )) ?></span> </a> </span> </td> <?php else :?> <td class = "col price" data-th= "<?= $block->escapeHtml(__('Price')) ?>" > <?= $block ->getUnitPriceHtml( $_item ) ?> </td> <?php endif ; ?> <td class = "col qty" data-th= "<?= $block->escapeHtml(__('Qty')) ?>" > <div class = "field qty" > <div class = "control qty custom-qty clearfix" > <label for = "cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty" > <span class = "label" ><?= $block ->escapeHtml(__( 'Qty' )) ?></span> <a class = "alo_qty alo_qty_dec ajax-cart-qty-minus" href= "javascript:void(0)" ></a> <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" step= "any" title= "<?= $block->escapeHtmlAttr(__('Qty')) ?>" class = "input-text qty" data-validate= "{required:true,'validate-greater-than-zero':true}" data-role= "cart-item-qty" /> <a class = "alo_qty alo_qty_inc ajax-cart-qty-plus" href= "javascript:void(0)" ></a> </label> </div> </div> </td> <td class = "col subtotal" data-th= "<?= $block->escapeHtml(__('Subtotal')) ?>" > <?php if ( $canApplyMsrp ) :?> <span class = "cart msrp subtotal" >--</span> <?php else :?> <?= $block ->getRowTotalHtml( $_item ) ?> <?php endif ; ?> </td> </tr> <tr class = "item-actions" > <td colspan= "4" > <div class = "actions-toolbar" > <?= /* @noEscape */ $block ->getActions( $_item ) ?> </div> </td> </tr> </tbody> <script type= "text/javascript" > require ([ 'jquery' , 'AjaxCart' ], function ($) { }); </script> |
As per highlighted code in above files, we will add our JS files.
First we will add our JS configuration in app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/requirejs-config.js file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var config = { map: { '*' : { 'AjaxCart' : 'Magelearn_AjaxShoppingCartUpdate/js/cartValueIncDec' , 'CartQtyUpdate' : 'Magelearn_AjaxShoppingCartUpdate/js/cartQtyUpdate' } }, shim: { AjaxCart: { deps: [ 'jquery' ] }, CartQtyUpdate: { deps: [ 'jquery' ] } } }; |
Now as per filepath defined in above file add app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/web/js/cartValueIncDec.js file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | define([ 'jquery' ], function ($) { "use strict" ; function ajaxCartUpdate() { $( '.main' ).on( "click" , '.alo_qty_dec' , function () { var input = $(this).parent().find( 'input' ); var value = parseInt(input.val()); if (value) input.val(value - 1); }); $( '.main' ).on( "click" , '.alo_qty_inc' , function () { var input = $(this).parent().find( 'input' ); var value = parseInt(input.val()); input.val(value + 1); }); } ajaxCartUpdate(); }); |
And app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/web/js/cartQtyUpdate.js file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | define([ 'jquery' ], function ($) { "use strict" ; function cartQtyupdate() { 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); require ([ 'Magento_Checkout/js/action/get-totals' , 'Magento_Customer/js/customer-data' ], function (getTotalsAction, customerData) { // The mini cart reloading customerData.reload(sections, true); // The totals summary block reloading var deferred = $.Deferred(); getTotalsAction([], deferred); //Display error if found after jquery var messages = $.cookieStorage.get( 'mage-messages' ); if (!_.isEmpty(messages)) { customerData.set( 'messages' , {messages: messages}); $.cookieStorage.set( 'mage-messages' , '' ); } }); }, error: function (xhr, status, error) { var err = eval ( "(" + xhr.responseText + ")" ); console.log(err.Message); } }); } $(document).on( 'change' , '.custom-qty input' , function () { cartQtyupdate(); }); $(document).on( 'click' , '.custom-qty a' , function () { cartQtyupdate(); }); }); |
Now to add +/- qty on cart items and AJAX operation on checkout page we will add app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/layout/checkout_index_index.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | < page xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation = "urn:magento:framework:View/Layout/etc/page_configuration.xsd" > < body > < referenceBlock name = "checkout.root" > < arguments > < argument name = "jsLayout" xsi:type = "array" > < item name = "components" xsi:type = "array" > < item name = "checkout" xsi:type = "array" > < item name = "children" xsi:type = "array" > < item name = "sidebar" xsi:type = "array" > < item name = "children" xsi:type = "array" > < item name = "summary" xsi:type = "array" > < item name = "children" xsi:type = "array" > < item name = "cart_items" xsi:type = "array" > < item name = "children" xsi:type = "array" > < item name = "details" xsi:type = "array" > < item name = "component" xsi:type = "string" >Magelearn_AjaxShoppingCartUpdate/js/view/summary/item/details</ item > </ item > </ item > </ item > </ item > </ item > </ item > </ item > </ item > </ item > </ item > </ argument > </ arguments > </ referenceBlock > </ body > </ page > |
Now as per path defined in above layout file, we will add our JS component file at app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/web/js/view/summary/item/details.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | define([ 'jquery' , 'uiComponent' , 'Magento_Customer/js/model/authentication-popup' , 'Magento_Customer/js/customer-data' , 'Magento_Checkout/js/model/quote' , 'Magento_Checkout/js/action/get-totals' , 'Magento_Checkout/js/model/totals' , 'Magento_Checkout/js/model/cart/totals-processor/default' , 'Magento_Checkout/js/model/cart/cache' , 'Magento_Checkout/js/model/shipping-service' , 'Magento_Checkout/js/model/shipping-rate-registry' , 'Magento_Checkout/js/model/resource-url-manager' , 'mage/storage' , 'Magento_Checkout/js/model/error-processor' , 'mage/url' , 'Magento_Ui/js/modal/alert' , 'Magento_Ui/js/modal/confirm' , 'underscore' , 'escaper' , 'jquery/ui' , 'mage/decorate' , 'mage/collapsible' , 'mage/cookies' ], function ($, Component, authenticationPopup, customerData, quote, getTotalsAction, totals, defaultTotal, cartCache, shippingService, rateRegistry, resourceUrlManager, storage, errorProcessor, url, alert, confirm, _, escaper) { 'use strict' ; return Component.extend({ shoppingCartUrl: window.checkout.shoppingCartUrl, defaults: { template: 'Magelearn_AjaxShoppingCartUpdate/summary/item/details' , allowedTags: [ 'b' , 'strong' , 'i' , 'em' , 'u' ] }, /** * @param {Object} quoteItem * @return {String} */ getNameUnsanitizedHtml: function (quoteItem) { var txt = document.createElement( 'textarea' ); txt.innerHTML = quoteItem.name; return escaper.escapeHtml(txt.value, this.allowedTags); }, /** * @param {Object} quoteItem * @return {String}Magento_Checkout/js/region-updater */ getValue: function (quoteItem) { return quoteItem.name; }, updateItemQtyCheckout: function (data, event) { var btnminus = "" ; var btnplus = "" ; if (event.target.classList[1] == "minus" ) { btnminus = event.currentTarget.dataset.btnMinus; } if (event.target.classList[1] == "plus" ) { btnplus = event.currentTarget.dataset.btnPlus; } var itemId = event.currentTarget.dataset.cartItem; // If element is minus and quantity is '1' than remove var elem = $( '#cart-item-' + itemId + '-qty' ); if (event.target.classList[1] == 'plus' ) { elem.val(parseInt(elem.val()) + 1) } else if (event.target.classList[1] == 'minus' ) { elem.val(parseInt(elem.val()) - 1) } if (event.target.classList[1] == "minus" && $( '#cart-item-' + itemId + '-qty' ).val() == '0' ) { var productData = this._getProductById(Number(itemId)); if (!_.isUndefined(productData)) { var self = this; var elemr = elem; self._ajax(url.build( 'checkout/sidebar/removeItem' ), { 'item_id' : itemId }, elemr, self._removeItemAfter); if (window.location.href === self.shoppingCartUrl) { window.location.reload(false); } } } else { this._ajax(url.build( 'checkout/sidebar/updateItemQty' ), { 'item_id' : itemId, 'item_qty' : $( '#cart-item-' + itemId + '-qty' ).val(), 'item_btn_plus' : btnplus, 'item_btn_minus' : btnminus }, elem, this._updateItemQtyAfter); } }, _getProductById: function (productId) { return _.find(customerData.get( 'cart' )().items, function (item) { return productId === Number(item[ 'item_id' ]); }); }, _updateItemQtyAfter: function (elem) { var productData = this._getProductById(Number(elem.data( 'cart-item' ))); if (!_.isUndefined(productData)) { $(document).trigger( 'ajax:updateCartItemQty' ); if (window.location.href === this.shoppingCartUrl) { window.location.reload(false); } } this._hideItemButton(elem); this._customerData(); }, _customerData: function () { var deferred = $.Deferred(); getTotalsAction([], deferred); var sections = [ 'cart' ]; customerData.invalidate(sections); customerData.reload(sections, true); var totals_obj = totals.totals; totals_obj.subscribe( function (newTotalvalue) { //console.dir(newTotalvalue['items'].length); if (window.checkoutConfig.useQty == true) { $( '.items-in-cart strong span:first' ).html(newTotalvalue[ 'items_qty' ]); } }); var self = this; self._estimateTotalsAndUpdateRatesCheckout(); }, _ajax: function (url, data, elem, callback) { $.extend(data, { 'form_key' : $.mage.cookies.get( 'form_key' ) }); $.ajax({ url: url, data: data, type: 'post' , dataType: 'json' , context: this, /** @inheritdoc */ beforeSend: function () { elem.attr( 'disabled' , 'disabled' ); }, /** @inheritdoc */ complete: function () { elem.attr( 'disabled' , null); } }) .done( function (response) { var msg; if (response.success) { callback.call(this, elem, response); } else { msg = response[ 'error_message' ]; if (msg) { alert({ content: msg }); } } }) .fail( function (error) { console.log(JSON.stringify(error)); }); }, _hideItemButton: function (elem) { var itemId = elem.data( 'cart-item' ); $( '#update-cart-item-' + itemId).hide( 'fade' , 300); }, _removeItemAfter: function (elem) { var productData = this._getProductById(Number(elem.data( 'cart-item' ))); if (!_.isUndefined(productData)) { $(document).trigger( 'ajax:removeFromCart' , { productIds: [productData[ 'product_id' ]] }); var sections = [ 'cart' ]; setTimeout( function () { if (customerData.get( 'cart' )().items.length == 0) { window.location.reload(); } }, 2000); if (window.location.href.indexOf(this.shoppingCartUrl) === 0) { window.location.reload(); } } this._customerData(); }, _estimateTotalsAndUpdateRatesCheckout: function () { var serviceUrl, payload; var address = quote.shippingAddress(); shippingService.isLoading(true); serviceUrl = resourceUrlManager.getUrlForEstimationShippingMethodsForNewAddress(quote); payload = JSON.stringify({ address: { 'street' : address.street, 'city' : address.city, 'region_id' : address.regionId, 'region' : address.region, 'country_id' : address.countryId, 'postcode' : address.postcode, 'email' : address.email, 'customer_id' : address.customerId, 'firstname' : address.firstname, 'lastname' : address.lastname, 'middlename' : address.middlename, 'prefix' : address.prefix, 'suffix' : address.suffix, 'vat_id' : address.vatId, 'company' : address.company, 'telephone' : address.telephone, 'fax' : address.fax, 'custom_attributes' : address.customAttributes, 'save_in_address_book' : address.saveInAddressBook } } ); storage.post( serviceUrl, payload, false ).done( function (result) { rateRegistry.set(address.getCacheKey(), result); shippingService.setShippingRates(result); }).fail( function (response) { shippingService.setShippingRates([]); errorProcessor.process(response); }).always( function () { shippingService.isLoading(false); }); } }); }); |
Also will add our html file at app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/web/template/summary/item/details.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | <!-- ko foreach : getRegion( 'before_details' ) --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> <div class = "product-item-details" > <div class = "product-item-inner" > <div class = "product-item-name-block" > <strong class = "product-item-name" data-bind= "html: getNameUnsanitizedHtml($parent)" ></strong> <div class = "details-qty" > <span class = "label" ><!-- ko i18n: 'Qty' --><!-- /ko --></span> <span class = "value" data-bind= "text: $parent.qty" ></span> <!-- new code start --> <button data-bind="attr: { id: 'minus-cart-item-' + $parent .item_id, 'data-cart-item' : $parent .item_id, 'data-btn-minus' : 'minus' , },click:updateItemQtyCheckout" class = "update-cart-item minus" > - </button> <input data-bind="attr: { id: 'cart-item-' + $parent .item_id+ '-qty' , 'data-cart-item' : $parent .item_id, 'data-item-qty' : $parent .qty, 'data-cart-item-id' : $parent .product_sku }, value: $parent .qty" type= "number" size= "4" class = "item-qty cart-item-qty" readonly> <button data-bind="attr: { id: 'plus-cart-item-' + $parent .item_id, 'data-cart-item' : $parent .item_id, 'data-btn-plus' : 'plus' },click:updateItemQtyCheckout" class = "update-cart-item plus" > <!--<span data-bind= "i18n: '+'" ></span>--> + </button> <button data-bind="attr: { id: 'update-cart-item-' + $parent .item_id, 'data-cart-item' : $parent .item_id, title: $t ( 'Update' ) }" class = "update-cart-item" style= "display: none" > <span data-bind= "i18n: 'Update'" > </span> </button> <!-- new code ends --> </div> </div> <!-- ko foreach : getRegion( 'after_details' ) --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </div> <!-- ko if : (JSON.parse( $parent .options).length > 0)--> <div class = "product options" data-bind= "mageInit: {'collapsible':{'openedState': 'active'}}" > <span data-role= "title" class = "toggle" ><!-- ko i18n: 'View Details' --><!-- /ko --></span> <div data-role= "content" class = "content" > <strong class = "subtitle" ><!-- ko i18n: 'Options Details' --><!-- /ko --></strong> <dl class = "item-options" > <!--ko foreach : JSON.parse( $parent .options)--> <dt class = "label" data-bind= "text: label" ></dt> <!-- ko if : ( $data .full_view)--> <!-- ko with: {full_viewUnsanitizedHtml: $data .full_view}--> <dd class = "values" data-bind= "html: full_viewUnsanitizedHtml" ></dd> <!-- /ko --> <!-- /ko --> <!-- ko ifnot: ( $data .full_view)--> <!-- ko with: {valueUnsanitizedHtml: $data .value}--> <dd class = "values" data-bind= "html: valueUnsanitizedHtml" ></dd> <!-- /ko --> <!-- /ko --> <!-- /ko --> </dl> </div> </div> <!-- /ko --> </div> <!-- ko foreach : getRegion( 'item_message' ) --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> |
We will also add some CSS to display it more properly at app/code/Magelearn/AjaxShoppingCartUpdate/view/frontend/web/css/source/_module.less
0 Comments On "Update Shopping Cart items quantity with AJAX on Checkout/cart and Checkout Page. Display Alert before remove items from cart on Checkout/cart Page"