3

I need to add a quantity increment button in cart page and mini cart popup like this.

enter image description here

I added the button but I can't assign the functionality.
This is what I did app/code/Amsi/UserManagement/view/frontend/layout/checkout_cart_index.xml

<?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">
            <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.item.renderers.override" as="renderer.list.custom"/>
            <arguments>
                <argument name="renderer_list_name" xsi:type="string">checkout.cart.item.renderers.override</argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

app/code/Amsi/UserManagement/view/frontend/layout/checkout_cart_item_renderers.xml

<?xml version="1.0"?>
<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.cart.item.renderers.override">
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="default" template="Amsi_UserManagement::cart/item/default.phtml" />

            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="simple" template="Amsi_UserManagement::cart/item/default.phtml" />
        </referenceBlock>
    </body>
</page>

app/code/Amsi/UserManagement/view/frontend/templates/cart/item/default.phtml

.......
<td class="col qty" data-th="<?= $block->escapeHtml(__('Qty')) ?>">
    <div class="field qty">
        <label class="label" for="cart-<?= /* @escapeNotVerified */ $_item->getId() ?>-qty">
            <span><?= /* @escapeNotVerified */ __('Qty') ?></span>
        </label>
        <div class="control qty">
            <button>-</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 >+</button>
        </div>
    </div>
</td>
......

How can i assign functionality to increment and decrements buttons ?

3
  • You jQuery to add functionality.
    – aravind
    Commented Mar 8, 2018 at 6:09
  • Where should i define my jquery function ? Commented Mar 8, 2018 at 6:15
  • 1
    Create a custom module for those increment & decrement field.
    – aravind
    Commented Mar 8, 2018 at 6:27

4 Answers 4

13

app/code/Amsi/UserManagement/view/frontend/templates/cart/item/default.phtml

I have added For both increment and decrementing quantity.

You can add the button near Quantiy using below code.

<div class="control qty">
   <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"/>                                                     

      /*Code to add increment and decrement button*/

   <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>

<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>
4
  • 1
    Your code is almost correct but it will work only when you are having 1 product in cart. Because increment and decrement in your code is managed by increment / decrement button's class i.e "increaseQty" & "decreaseQty". So if you want to make is available for n numbers of products in cart then you are required to replace this line in above code "$('.increaseQty, .decreaseQty').on("click",function(){" with this line "$('#<?php echo $_item->getId();?>-upt, #<?php echo $_item->getId();?>-dec').on("click",function(){". Hence right now I have managed using ID so it will work perfect.
    – LR Soni
    Commented Sep 27, 2018 at 19:34
  • How does this trigger a change event so ko knows to show the 'update' button? I'm able to get the + - buttons working and changing the input value, but the 'update' button does not appear to actually save and update the cart
    – iamface
    Commented Oct 18, 2018 at 14:52
  • 1
    hi @aravind, above code works in cart page, not on minicart Commented Feb 21, 2019 at 8:37
  • Since minicart is rendered using KO.You need to override "module-checkout/view/frontend/web/template/minicart/item/default.html" file in vendor
    – aravind
    Commented Feb 25, 2019 at 6:06
1

Try with below code.

If you don't have the files in below path, create a file with same name and copy & paste below code.

File Path: app\design\frontend\Sm\destino\Magento_Checkout\web\template\minicart\item\default.html

<!--
/**
 * 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) && option.option_type == 'file') -->
                                <span data-bind="html: option.value"></span>
                            <!-- /ko -->
                            <!-- ko if: (!Array.isArray(option.value) && option.option_type != 'file') -->
                                <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>
                           
                    <span class="less">-</span>
                    <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">                    
                    <span class="more">+</span>
                    <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>
</li>

File path: app\design\frontend\Sm\destino\Magento_Checkout\templates\cart\minicart.phtml

If you don't have minicart.phtml file. copy from vendor folder and add below javascript.

Vendor file path: vendor\magento\module-checkout\view\frontend\templates\cart\minicart.phtml

<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>

If you want my design, add below code in your less file.

.minicart-items{
    .item{
        .product{
            .product-item-details{
                .details-qty{
                    .more{
                        border: 1px solid #dddddd;
                        height: 32px !important;
                        width: 20px;
                        text-align: center;
                        display: inline-block;
                        vertical-align: middle;
                        line-height: 30px;
                        margin: 0;
                        padding: 0;
                    }

                    .less{
                        border: 1px solid #dddddd;
                        height: 32px !important;
                        width: 20px;
                        text-align: center;
                        display: inline-block;
                        vertical-align: middle;
                        line-height: 30px;
                        margin: 0;
                        padding: 0;
                    }
                }
            }
        }
    }
}
0
<div class="field qty">
                <label class="label" for="qty"><span><?php /* @escapeNotVerified */ echo __('Qty') ?></span></label>
                <div class="control">
                    <input type="number" name="qty" id="qty" maxlength="12" value="<?php /* @escapeNotVerified */ echo $block->getProductDefaultQty() * 1 ?>" title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty" data-validate="{'required-number':true,digits:true}"/>
                </div>
                <div class="qty-change">
                    <a href="javascript:void(0)" class="increaseQty">+</a>
                    <a href="javascript:void(0)" class="decreaseQty">-</a>
                </div>
            </div>

      <script>
require([
        'jquery',
        'mage/mage'
    ], function ($) {
        'use strict';

        $(".increaseQty").unbind('click').click(function () {
            if ($(this).parents('.field.qty').find("input.input-text.qty").is(':enabled')) {
                $(this).parents('.field.qty').find("input.input-text.qty").val((+$(this).parents('.field.qty').find("input.input-text.qty").val() + 1) || 0);
                $(this).parents('.field.qty').find("input.input-text.qty").trigger('change');
                $(this).focus();
            }
        });

        $(".decreaseQty").unbind('click').click(function () {
                if ($(this).parents('.field.qty').find("input.input- 
                        text.qty ").is(':enabled')){
                        $(this).parents('.field.qty').find("input.input- 
                            text.qty ").val(($(this).parents('.field.qty').find("
                            input.input -
                            text.qty ").val() - 1 > 0) 
                            ($(this).parents('.field.qty').find("input.input-text.qty").val() -
                                1): 0); $(this).parents('.field.qty').find("input.input-text.qty").trigger('change'); $(this).focus();
                    }
                });
        });

    </script>    
0

also you can do it the super fast way just inject this jQuery snippet in your html head

jQuery('#shopping-cart-table :input[type="number"]').bind('keyup mouseup', function () { jQuery(".update").click() });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.