Add Quantity Increment And Decrement Button on MiniCart

1.  Create custom module on the path:

app/code/Esparksinc/QtyCounterMinicart

You can follow the guide to create custom module in magento 2.

2. Create “default.html” file on the path:

app/code/Esparksinc/QtyCounterMiniCart/view/frontend/web/template/minicart/item

And paste the below code into it:


<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 
 */
-->
<li class="item product product-item overload" 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 ifnot: Array.isArray(option.value) -->
                                <span data-bind="html: 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>
                    <button name="decrement"  onclick="qtyChange(event)" value="desc">-</button>
                    <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">
                    <button name="increment" onclick="qtyChange(event)" value="inc">+</button>
                    <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>

3. Create a requirejs-config.js file on the path.
    app/code/Esparksinc/QtyCounterMiniCart/view/frontend/

And paste this code into it:


var config = {
    map: {
        '*': {
            'Magento_Checkout/template/minicart/item/default.html': 'Esparksinc_QtyCounterMiniCart/template/minicart/item/default.html',
            qtychange: 'Esparksinc_QtyCounterMiniCart/js/qtychange'
        }
    }
};

4. Create a default.xml file on the path.
    app/code/Esparksinc/QtyCounterMiniCart/view/frontend/layout

And paste this code into it:


<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
    <referenceContainer name="before.body.end">
        <block class="Magento\Framework\View\Element\Template" name="exampleScript" template="Esparksinc_QtyCounterMiniCart::load.phtml" after="-" />
    </referenceContainer>
</body>
</page>

5. Create a load.phtml file on the path.
    app/code/Esparksinc/QtyCounterMiniCart/view/frontend/templates

And paste this code into it:

<div>Before Body load</div>
<script>
    require(['jquery', 'jquery/ui', 'qtychange'], function($){
       //js code here
    });
</script>

6. Create a js file for example qtychange.js on the path.
    app/code/Esparksinc/QtyCounterMiniCart/view/frontend/web/js

And paste the following code into it:

function qtyChange(event){

    if(jQuery(event.target).val() == 'inc') { /* qty increase */
        var oldVal = jQuery(event.target).prev().val();

        if ( parseFloat(oldVal) >= 0 ) {

            var newVal = parseFloat(oldVal) + 1;

            jQuery(event.target).prev().val(newVal);

            jQuery(event.target).next().show();

        }
    }else{ /* qty decrease */

        var oldVal = jQuery(event.target).next().val();

        if (parseFloat(oldVal) >= 2) {

            var newVal = parseFloat(oldVal) - 1;

            jQuery(event.target).next().val(newVal);

            jQuery(event.target).next().next().next().show();

        }
    }

}

Run these commands:`

php bin/magento setup:upgrade 

php bin/magento cache:flush

See the result on mini cart popup: