Categories: Magento 2 Tutorials

Add Quantity Increment and Decrement Button in Magento 2 with KnockoutJS

Knockout is a javascript library which follows MVVM (Model-View-View-Model) Pattern and used for creating front end. You can easily handle complex data-driven interfaces using Knockout JS, and since it is open source, it is free to use. Knockout JS is lightweight and mostly used in checkout pages in Magento 2. However Knockout JS is slightly complex to implement in Magento 2, hence, this tutorial will teach you how to implement Knockout JS in Magento 2. On the product page, Magento 2 has a simple input text filed on product page for quantity and to make it easier for customers, you can add increment and decrement button in Magento 2. I will implement it using custom module and if you are not familiar with its implementation and usage, you can check out this guide: Custom Module in Magento 2. Let’s Start!

Create Directories

First, go to the root directory of your Magento 2 store and create directories as shown below:

Configure Module

Configure your module by creating a module.xml file in app/code/Magenticians/Mymodule/etc.Add the following code in it:
<?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="Magenticians_Mymodule" setup_version="1.0.0"></module>
</config>

Registration of Module

Now register the module by creating registration.php in app/code/Magenticians/Mymodule, and add the following code in it:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
   \Magento\Framework\Component\ComponentRegistrar::MODULE,
   'Magenticians_Mymodule',
   __DIR__
);

Copy addtocart.phtml

Go to vendor/magento/module-catalog/view/frontend/templates/product/view from the root directory of your store and copy addtocart.phtml to your own module app/code /Magenticians/Mymodule/view/frontend/templates/catalog/product/view. The addtocart.phtml file will looks like this:
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/// @codingStandardsIgnoreFile
/** @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><?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="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
                      />
           </div>
       </div>
       <?php endif; ?>
       <div class="actions">
           <button type="submit"
                   title="<?php /* @escapeNotVerified */ echo $buttonTitle ?>"
                   class="action primary tocart"
                   id="product-addtocart-button">
               <span><?php /* @escapeNotVerified */ echo $buttonTitle ?></span>
           </button>
           <?php echo $block->getChildHtml('', true) ?>
       </div>
   </div>
</div>
<?php endif; ?>
<script type="text/x-magento-init">
   {
       "#product_addtocart_form": {
           "Magento_Catalog/product/view/validation": {
               "radioCheckboxClosest": ".nested"
           }
       }
   }
</script>
<?php if (!$block->isRedirectToCartEnabled()) : ?>
<script type="text/x-magento-init">
   {
       "#product_addtocart_form": {
           "catalogAddToCart": {
               "bindSubmit": false
           }
       }
   }
</script>
<?php endif; ?>

Edit addtocart.phtml

In addtocart.phtml, create a UI component and initialize it. To do that, first add the script below above the input field of quantity:
<script type="text/x-magento-init">
{
   "*": {
           "Magento_Ui/js/core/app": {
               "components": {
                   "qty_change": {
                       "component": "Magenticians_Mymodule/js/view/product/view/qty_change",
                       "defaultQty": <?php echo $block->getProductDefaultQty() * 1 ?>
                   }
               }
           }
   }
}
</script>
Now connect the component qty_change with the following frontend HTML:
<div class="control" data-bind="scope: 'qty_change'">
   <button data-bind="click: decreaseQty">-</button>
   <input  data-bind="value: qty()"
   type="number"
   name="qty"
   id="qty"
   maxlength="12"
   title="<?php echo __('Qty') ?>"
   class="input-text qty"
   data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
   />
   <button data-bind="click: increaseQty">+</button>
</div>
Data-bind attribute: Connect HTML with a Javascript function of our component qty_change. In the code above, there are two buttons which I have connected to the component by using Javascript click event which will be used to decrease/increase the quantity value. The final addtocart.phtml file will looks like this:
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/// @codingStandardsIgnoreFile
/** @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><?php /* @escapeNotVerified */ echo __('Qty') ?></span></label>

<script type="text/x-magento-init">
{
   "*": {
           "Magento_Ui/js/core/app": {
               "components": {
                   "qty_change": {
                       "component": "Magenticians_Mymodule/js/view/product/view/qty_change",
                       "defaultQty": <?php echo $block->getProductDefaultQty() * 1 ?>
                   }
               }
           }
   }
}
</script>

<div class="control" data-bind="scope: 'qty_change'">
   <button data-bind="click: decreaseQty">-</button>
   <input  data-bind="value: qty()"
   type="number"
   name="qty"
   id="qty"
   maxlength="12"
   title="<?php echo __('Qty') ?>"
   class="input-text qty"
   data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
   />

   <button data-bind="click: increaseQty">+</button>
</div>
       </div>
       <?php endif; ?>
       <div class="actions">
           <button type="submit"
                   title="<?php /* @escapeNotVerified */ echo $buttonTitle ?>"
                   class="action primary tocart"
                   id="product-addtocart-button">
               <span><?php /* @escapeNotVerified */ echo $buttonTitle ?></span>
           </button>
           <?php echo $block->getChildHtml('', true) ?>
       </div>
   </div>
</div>
<?php endif; ?>
<script type="text/x-magento-init">
   {
       "#product_addtocart_form": {
           "Magento_Catalog/product/view/validation": {
               "radioCheckboxClosest": ".nested"
           }
       }
   }
</script>
<?php if (!$block->isRedirectToCartEnabled()) : ?>
<script type="text/x-magento-init">
   {
       "#product_addtocart_form": {
           "catalogAddToCart": {
               "bindSubmit": false
           }
       }
   }
</script>
<?php endif; ?>

Create qty_change.js

Now create qty_change.js in app/code/Magenticians/Mymodule/view/frontend/web/js/view/product/view. Add the following code in it:
define([
   'ko',
   'uiComponent'
], function (ko, Component) {
   'use strict';
   return Component.extend({
       initialize: function () {
           //initialize parent Component
           this._super();
           this.qty = ko.observable(this.defaultQty);
       },
       decreaseQty: function() {
           var newQty = this.qty() - 1;
           if (newQty < 1) 
           {
               newQty = 1;
           }
           this.qty(newQty);
       },
       increaseQty: function() {
           var newQty = this.qty() + 1;
           this.qty(newQty);
       }
   });
});

Create catalog_product_view.xml

Lastly, just create catalog_product_view.xml in app/code/Magenticians/Mymodule/view/frontend/layout. Add the following code in it:
<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
   <body>
       <referenceBlock name="product.info.addtocart">
           <action method="setTemplate">
               <argument name="template" xsi:type="string">Magenticians_Mymodule::catalog/product/view/addtocart.phtml</argument>
           </action>
       </referenceBlock>
       <referenceBlock name="product.info.addtocart.additional">
           <action method="setTemplate">
               <argument name="template" xsi:type="string">Magenticians_Mymodule::catalog/product/view/addtocart.phtml</argument>
           </action>
       </referenceBlock>
   </body>
</page>
The purpose of the code above is to change the default addtocart.phtml template.

Run the Commands

Go to the root directory of your store by using SSH terminal and run the following commands:
rm -rf var/di var/generation var/cache/* var/log/* var/page_cache/*

php bin/magento module:enable Magenticians_Mymodule

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento indexer:reindex

php bin/magento cache:clean

php bin/magento cache:flush
Now go to the product page and you will see the result:

Final Words

Always try to make it easier for customers to buy products on your store as it can result in boosted sales. After following this tutorial, you should be able to add quantity increment decrement button in Magento 2 with Knockout JS, and you also learned the implementation of Knockout JS in Magento 2.
Syed Muneeb Ul Hasan

Syed Muneeb Ul Hasan is an expert in PHP and Magento, he prefers to educate users in implementing and learning Magento. When not working, he loves to watch cricket.

View Comments

Share
Published by
Syed Muneeb Ul Hasan

Recent Posts

Building Employee Trust and Dedication – A Complete Guide

In the highly competitive modern workplace, trust, and employee loyalty are crucial factors for long-term… Read More

3 months ago

12 Winning Strategies for Small Businesses Marketing

In the ever-evolving world of small business developing and implementing effective marketing strategies is critical to… Read More

3 months ago

Top 10 App Development Companies in Dubai 2024

With one of the highest internet penetration rates, the UAE has set out to revolutionize… Read More

3 months ago

Transforming Industries: How Amazons GPT44X is Revolutionizing AI Technology

Artificial Intelligence (AI) has been continually evolving, leading to remarkable advancements in various industries. Among… Read More

8 months ago

Top Magento 2 Extensions for 2023

Extensions, extensions and lots of extensions. We all love extensions, don’t we? After all, extensions… Read More

11 months ago

Unleashing the Power of Software Testing: Cooperating with a Testing Firm

Software quality is crucial to a firm's success across industries in the quickly changing digital… Read More

11 months ago