The E-commerce store owners always try to make the online shopping platform as easy as possible. By default Magento 2 allows, there are no increment/decrement quantity buttons.
So in order to improve the user experience you can add Increment/Decrement button.
You can add on PLP (Product Listing Page), PDP(Product Detail Page), Cart Page and in Mini cart also.
Product Listing Page : To add Quantity Increment/Decrement button on PLP, need to override the list.phtml
file in active theme.
Here I have made a theme vendor name V4U and theme name is Sampletheme.
File Path : app/design/frontend/V4U/Sampletheme/Magento_Catalog/templates/product/list.phtml
Add the below code to your list.phtml
before the “Add to Cart” button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<div class="field qty"> <div class="control qty-change"> <?php $id = "qty_".$_product->getId(); ?> <button type="button" class="reduced items" onclick="var result = document.getElementById('<?= $id ?>'); var qty = result.value; if( !isNaN( qty ) && qty > 1 ) result.value--;return false;">-</button> <input type="text" name="qty" id="<?= $id ?>" value="1" title="<?= /* @escapeNotVerified */ __('Qty') ?>" class="input-text qty" data-validate="<?= $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>" /> <button type="button" class="increase items" onclick="var result = document.getElementById('<?= $id ?>'); var qty = result.value; if( !isNaN( qty )) result.value++;return false;">+</button> </div> </div> |
Product Detail Page : To add Quantity Increment/Decrement button on PDP, need to override the addtocart.phtml
file in active theme.
File Path : app/design/frontend/V4U/Sampletheme/Magento_Catalog/templates/product/view/addtocart.phtml
Add qty-default
class in input type in number.
Now add below span tag and jQuery script in addtocart.phtml
file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<div class="control-qty"> <span class="quantity-controls quantity-plus">+</span> <span class="quantity-controls quantity-minus">-</span> <script type="text/javascript"> require([ 'jquery' ], function ($) { $('.quantity-plus').click(function () { $('.qty-default').val(Number($('.qty-default').val()) + 1); }); $('.quantity-minus').click(function () { var value = Number($('.qty-default').val()) - 1; if (value > 0) { $('.qty-default').val(value); } }); }); </script> </div> |
And Now addtocart.phtml
looks like
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 |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** @var $block \Magento\Catalog\Block\Product\View */ ?> <?php $_product = $block->getProduct(); ?> <?php $buttonTitle = __('Add to Cart'); ?> <?php if ($_product->isSaleable()) :?> <div class="box-tocart"> <div class="fieldset"> <?php if ($block->shouldRenderQuantity()) :?> <div class="field qty"> <label class="label" for="qty"><span><?= $block->escapeHtml(__('Qty')) ?></span></label> <div class="control"> <input type="number" name="qty" id="qty" min="0" value="<?= $block->getProductDefaultQty() * 1 ?>" title="<?= $block->escapeHtmlAttr(__('Qty')) ?>" class="qty-default input-text qty" data-validate="<?= $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>" /> <div class="control-qty"> <span class="quantity-controls quantity-plus">+</span> <span class="quantity-controls quantity-minus">-</span> <script type="text/javascript"> require([ 'jquery' ], function ($) { $('.quantity-plus').click(function () { $('.qty-default').val(Number($('.qty-default').val()) + 1); }); $('.quantity-minus').click(function () { var value = Number($('.qty-default').val()) - 1; if (value > 0) { $('.qty-default').val(value); } }); }); </script> </div> </div> </div> <?php endif; ?> <div class="actions"> <button type="submit" title="<?= $block->escapeHtmlAttr($buttonTitle) ?>" class="action primary tocart" id="product-addtocart-button" disabled> <span><?= $block->escapeHtml($buttonTitle) ?></span> </button> <?= $block->getChildHtml('', true) ?> </div> </div> </div> <?php endif; ?> <script type="text/x-magento-init"> { "#product_addtocart_form": { "Magento_Catalog/js/validate-product": {} } } </script> |
Cart Page : To add Quantity Increment/Decrement button on Cart Page, need to override the default.phtml
file in active theme.
File Path : app/design/frontend/V4U/Sampletheme/Magento_Checkout/templates/cart/item/default.phtml
Now add below two buttons after control qty
class.
1 2 3 4 |
<div class="qty_control"> <button type="button" id="<?= /* @escapeNotVerified */ $_item->getId() ?>-upt" class="increaseQty">+</button> <button type="button" id="<?= /* @escapeNotVerified */ $_item->getId() ?>-dec" class="decreaseQty">-</button> </div> |
Now add below jQuery Script in the end of file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<script type="text/javascript"> require(["jquery"],function($){ $('#<?php echo $_item->getId();?>-upt, #<?php echo $_item->getId();?>-dec').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); }else{ if(currentQty>1){ var newAdd = parseInt(currentQty)-parseInt(1); $("#cart-"+ctrl+"-qty").val(newAdd); } } }); }); </script> |
And Now default.phtml
looks like
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 |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ // phpcs:disable Magento2.Templates.ThisInTemplate // phpcs:disable Magento2.Files.LineLength.MaxExceeded /** @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"> <label for="cart-<?= $block->escapeHtmlAttr($_item->getId()) ?>-qty"> <span class="label"><?= $block->escapeHtml(__('Qty')) ?></span> <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"/> </label> </div> <div class="qty_control"> <button type="button" id="<?= /* @escapeNotVerified */ $_item->getId() ?>-upt" class="increaseQty">+</button> <button type="button" id="<?= /* @escapeNotVerified */ $_item->getId() ?>-dec" class="decreaseQty">-</button> </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"],function($){ $('#<?php echo $_item->getId();?>-upt, #<?php echo $_item->getId();?>-dec').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); }else{ if(currentQty>1){ var newAdd = parseInt(currentQty)-parseInt(1); $("#cart-"+ctrl+"-qty").val(newAdd); } } }); }); </script> |
Mini Cart : To add Quantity Increment/Decrement button on Mini Cart, need to override the minicart.phtml
& default.html
files in active theme.
File Path : app/design/frontend/V4U/Sampletheme/Magento_Checkout/templates/cart/minicart.phtml
Now add below jQuery Script in minicart.phtml
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 |
<script type="text/javascript"> require(["jquery"],function($){ $('body').on("click",".more, .less",function(){ var obj = $(this); var currentQty = obj.siblings('.cart-item-qty').val(); var iid = obj.siblings('.update-cart-item').attr('data-cart-item'); if(obj.hasClass('more')){ var newAdd = parseInt(currentQty)+parseInt(1); obj.siblings('.cart-item-qty').val(newAdd); obj.siblings('.cart-item-qty').attr('data-item-qty',newAdd); //$('#update-cart-item-'+iid).click(); $('.update-cart-item').show(); } else { if(parseInt(currentQty) > 1){ var newAdd = parseInt(currentQty)-parseInt(1); obj.siblings('.cart-item-qty').val(newAdd); obj.siblings('.cart-item-qty').attr('data-item-qty',newAdd); //$('#update-cart-item-'+iid).click(); $('.update-cart-item').show(); } } }); }); </script> |
And now add below two classes in default.html
inside the details-qty qty
class.
File Path : app/design/frontend/V4U/Sampletheme/Magento_Checkout/web/template/minicart/item/default.html
1 2 3 |
<div class="more">+</div> <div class="less">-</div> |
Now default.html
looks like
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 |
<!-- /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <li class="item product product-item" data-role="product-item"> <div class="product"> <!-- ko if: product_has_url --> <a data-bind="attr: {href: product_url, title: product_name}" tabindex="-1" class="product-item-photo"> <!-- ko foreach: $parent.getRegion('itemImage') --> <!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko --> <!-- /ko --> </a> <!-- /ko --> <!-- ko ifnot: product_has_url --> <span class="product-item-photo"> <!-- ko foreach: $parent.getRegion('itemImage') --> <!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko --> <!-- /ko --> </span> <!-- /ko --> <div class="product-item-details"> <strong class="product-item-name"> <!-- ko if: product_has_url --> <a data-bind="attr: {href: product_url}, html: product_name"></a> <!-- /ko --> <!-- ko ifnot: product_has_url --> <!-- ko text: product_name --><!-- /ko --> <!-- /ko --> </strong> <!-- ko if: options.length --> <div class="product options" data-mage-init='{"collapsible":{"openedState": "active", "saveState": false}}'> <span data-role="title" class="toggle"><!-- ko i18n: 'See Details' --><!-- /ko --></span> <div data-role="content" class="content"> <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong> <dl class="product options list"> <!-- ko foreach: { data: options, as: 'option' } --> <dt class="label"><!-- ko text: option.label --><!-- /ko --></dt> <dd class="values"> <!-- ko if: Array.isArray(option.value) --> <span data-bind="html: option.value.join('<br>')"></span> <!-- /ko --> <!-- ko if: (!Array.isArray(option.value) && ['file', 'html'].includes(option.option_type)) --> <span data-bind="html: option.value"></span> <!-- /ko --> <!-- ko if: (!Array.isArray(option.value) && !['file', 'html'].includes(option.option_type)) --> <span data-bind="text: option.value"></span> <!-- /ko --> </dd> <!-- /ko --> </dl> </div> </div> <!-- /ko --> <div class="product-item-pricing"> <!-- ko if: canApplyMsrp --> <div class="details-map"> <span class="label" data-bind="i18n: 'Price'"></span> <span class="value" data-bind="i18n: 'See price before order confirmation.'"></span> </div> <!-- /ko --> <!-- ko ifnot: canApplyMsrp --> <!-- ko foreach: $parent.getRegion('priceSidebar') --> <!-- ko template: {name: getTemplate(), data: item.product_price, as: 'price'} --><!-- /ko --> <!-- /ko --> <!-- /ko --> <div class="details-qty qty"> <label class="label" data-bind="i18n: 'Qty', attr: { for: 'cart-item-'+item_id+'-qty'}"></label> <div class="more">+</div> <input data-bind="attr: { id: 'cart-item-'+item_id+'-qty', 'data-cart-item': item_id, 'data-item-qty': qty, 'data-cart-item-id': product_sku }, value: qty" type="number" size="4" class="item-qty cart-item-qty"> <div class="less">-</div> <button data-bind="attr: { id: 'update-cart-item-'+item_id, 'data-cart-item': item_id, title: $t('Update') }" class="update-cart-item" style="display: none"> <span data-bind="i18n: 'Update'"></span> </button> </div> </div> <div class="product actions"> <!-- ko if: is_visible_in_site_visibility --> <div class="primary"> <a data-bind="attr: {href: configure_url, title: $t('Edit item')}" class="action edit"> <span data-bind="i18n: 'Edit'"></span> </a> </div> <!-- /ko --> <div class="secondary"> <a href="#" data-bind="attr: {'data-cart-item': item_id, title: $t('Remove item')}" class="action delete"> <span data-bind="i18n: 'Remove'"></span> </a> </div> </div> </div> </div> <div class="message notice" if="$data.message"> <div data-bind="text: $data.message"></div> </div> </li> |
After adding this need to run below Magento 2 commands :
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:clean
Happy Coding. Keep Liking & Sharing