How to add a free shipping bar to the top of a mini-cart

How to add a free shipping bar to the top of a mini-cart

Steps to create a free shipping bar

  • Create & register the module
  • Extend default.xml layout and define a block
  • Create block class & related template file (.phtml file)
  • Define jsLayout component in <block> element in default.xml layout
  • Create jsLayout component(.js file) & template(.html file) file at a location which is defined in default.xml layout file
  • Calculate percentage and binding it with shipping progress bar using knockout js.
  • Create a configuration menu to set the maximum price for free shipping bar at admin panel
  • Get maximum price config value for shipping bar which is set from the admin panel, and bind it to the shipping progress bar.
  1. Create a Module for Free Shipping Bar

Let’s create the separate module to add a free shipping bar to the top of the mini-cart.

You have to create a vendor directory under the app/code directory and a module directory under newly created vendor directory.

Create Vendor & Module directory as follow :

app/code/Kiwicommerce/Shippingbar

  1. Create registration.php file

Create a registration.php file on the root folder of your module for module registration and add the following content:

\Magento\Framework\Component\ComponentRegistrar::register(
   \Magento\Framework\Component\ComponentRegistrar::MODULE,
   'Kiwicommerce_Shippingbar',
   __DIR__
);
  1. Create module.xml file

For our module instruction, create a new directory “etc” on the root directory. Also, create a module.xml file under “etc” directory and add the following content:

<?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="Kiwicommerce_Shippingbar" setup_version="1.0.0">
       <sequence>
           <module name="Magento_Checkout"/>
           <module name="Magento_Tax"/>
       </sequence>
   </module>
</config>

In the <sequence> element add the Magento core modules that you want to load before the current module.

Run the following command using the command line interface from the Magento root directory to enable the module:

$ php ./bin/magento setup:upgrade

  1. Extend default.xml layout to add shipping bar block

To add a new block for the shipping bar in the minicart section, we need to extend layout from the Magento checkout core module.

To extend the layout, we need to create a default.xml layout at the following location:

app/code/Kiwicommerce/Shippingbar/view/frontend/layout/default.xml

Add the following content in the default.xml file to create the new block for the shipping bar:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
   <body>
       <referenceContainer name="minicart.addons">
           <block class="Kiwicommerce\Shippingbar\Block\Cart\Sidebar" name="shipping_bar" template="Kiwicommerce_Shippingbar::cart/minicart.phtml">
               <arguments>
                   <argument name="jsLayout" xsi:type="array">
                       <item name="components" xsi:type="array">
                           <item name="minicart-addons" xsi:type="array">
                               <item name="component" xsi:type="string">Kiwicommerce_Shippingbar/js/view/minicartaddons</item>
                               <item name="config" xsi:type="array">
                                   <item name="template" xsi:type="string">Kiwicommerce_Shippingbar/minicartaddons/content</item>
                               </item>
                           </item>
                       </item>
                   </argument>
               </arguments>
           </block>
       </referenceContainer>
   </body>
</page>
  1. Create block class and template files for the block

Create block class for the newly added block at the location below. We will use this class to set dynamic configuration for maximum price of free shipping bar in the future:

app/code/Kiwicommerce/Shippingbar/Block/Cart/Sidebar.php

Add following content in the Sidebar.php file,

<?php
namespace Kiwicommerce\Shippingbar\Block\Cart;

use Magento\Framework\View\Element\Template;

class Sidebar extends Template
{
   /**
    * Sidebar constructor.
    * @param Template\Context $context
    * @param array $data
    */
   public function __construct(
       Template\Context $context,
       array $data = []
   ) {
       parent::__construct($context, $data);
   }
}

Create a template to render the content of the knockout js template file at the following location with given content:

app/code/Kiwicommerce/Shippingbar/view/frontend/template/cart/minicart.phtml

<div id="cart-page">
   <div id="block-cart-list" data-bind="scope:'minicart-addons'" class="block">
       <!-- ko template: getTemplate() --><!-- /ko -->
       <script type="text/x-magento-init">
         {
             "#block-cart-list": {
                 "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
             },
             "*": {
                 "Magento_Ui/js/block-loader": "<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-1.gif') ?>"
             }
         }
     </script>
   </div>
</div>

Make sure that in the data-bind attribute, the scope name should be the name of our jsLayout component that we had defined in the default.xml file.

  1. Create the jsLayout component & template file

Now, we have to create the jsLayout component file as well as related template file as per defined in the default.xml file.

  • Create a component file at the following location:

app/code/Kiwicommerce/Shippingbar/view/frontend/web/js/view/minicartaddons.js

  • Create a component template file at the following location:

app/code/Kiwicommerce/Shippingbar/view/frontend/web/template/minicartaddons/content.html

Add the following content in the template file content.html

<div class="component-wrapper" data-bind="if: getTotalCartItems() > 0">
   <h4 data-bind="text : getpercentage() < 100 ?'Free shipping' : 'Eligible for free shipping!'"></h4>
   <span data-bind="html: cart().subtotal"></span><span> / </span><span data-bind="text: maxprice"></span>
   <div class="minprogress" id="progress">
       <div class="minprogress-active" id="child-progress" data-bind="style: { width: getpercentage() + '%' } "></div>
   </div>
</div>

Add the following content in the component file minicartaddons.js

define([
       'ko',
       'uiComponent',
       'Magento_Customer/js/customer-data',
   ], function (ko, Component, customerData) {
       'use strict';
       var subtotalAmount;
       var maxPrice = 100;
       var percentage;
       return Component.extend({
           displaySubtotal: ko.observable(true),
           maxprice: '$' + maxPrice.toFixed(2),
           /**
            * @override
            */
           initialize: function () {
               this._super();
               this.cart = customerData.get('cart');
           },
           getTotalCartItems: function () {
               return customerData.get('cart')().summary_count;
           },
           getpercentage: function () {
               subtotalAmount = customerData.get('cart')().subtotalAmount;
               if (subtotalAmount > maxPrice) {
                   subtotalAmount = maxPrice;
               }
               percentage = ((subtotalAmount * 100) / maxPrice);
               return percentage;
           }
       });
   });
  1. Create less file for the progress bar

Create miniprogress.less file for applying css of the progress bar at the following location with the code given below:

app/code/Kiwicommerce/Shippingbar/view/frontend/web/css/miniprogress.less

div.minprogress {
    border: 1px solid #a5a5a5;
    height: 10px;
    border-radius: 5px;
    position: relative;
.minprogress-active {
   position: absolute;
   background-color: #000000;
   height: 10px;
   border-radius: 5px;
}
}

Include miniprogress.less file in the <head> element before the <body> element at default.xml layout file by adding the following content:

<head>
   <css src="Kiwicommerce_Shippingbar::css/miniprogress.css"/>
</head>

The Free Shipping Bar has now been added in your mini-cart and you can see it in the screenshot below:

Shipping Bar

  1. Create system.xml file to add configuration menu to the admin panel

Now, we are going to add the configuration menu for free shipping bar in the store config menu on the admin side.

Create system.xml to add a new tab and section for the configuration of the shipping bar under store > configuration menu at the following location by adding the code snippet given below:

app/code/Kiwicommerce/Shippingbar/etc/adminhtml/system.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
   <system>
       <tab id="shippingbar" translate="label" sortOrder="1000">
           <label>Shipping Bar</label>
       </tab>
       <section id="shippingbar" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
           <label>Shipping Bar</label>
           <tab>shippingbar</tab>
           <resource>Kiwicommerce_Shippingbar::shippingbar</resource>
           <group id="shippingsection" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0">
               <label>Shipping Bar</label>
               <field id="shipping_bar" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="0" showInStore="0">
                   <label>Max Price</label>
                   <comment>Set Maximum price for free shipping.</comment>
               </field>
           </group>
       </section>
   </system>
</config>
  1. Create config.xml file to define a default value

Create a config.xml file to set a default maximum price value of shipping bar at the following location by adding the code given below:

app/code/Kiwicommerce/Shippingbar/etc/config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
   <default>
       <shippingbar>
           <shippingsection>
               <shipping_bar>100</shipping_bar>
           </shippingsection>
       </shippingbar>
   </default>
</config>

By making the above changes in the file, you will see that the configuration menu will appear at the store > configuration menu.
Shipping Bar Configuration

Now, we are going to fetch the default value of max price which is set in the admin panel and will reflect this in the shipping bar.

  1. Create helper to get a config value of shipping bar

To get the configuration value of max price for the shipping bar we need to create a helper at the following location with the below content:

app/code/Kiwicommerce/Shippingbar/Helper/Data.php

<?php
namespace Kiwicommerce\Shippingbar\Helper;

use Magento\Framework\App\Helper\AbstractHelper;

class Data extends AbstractHelper
{
   const PRICE_SHIPPING_BAR = 'shippingbar/shippingsection/shipping_bar';
   /**
    * Return if maximum price for shipping bar
    * @return int
    */
   public function getPriceForShippingBar()
   {
       return $this->scopeConfig->getValue(
           self::PRICE_SHIPPING_BAR,
           \Magento\Store\Model\ScopeInterface::SCOPE_STORE
       );
   }
}
  1. Use the helper to assign config value of shipping bar to the block

Now, we can use the above helper’s function using dependency injection concepts.

Replace the content of app/code/Kiwicommerce/Shippingbar/Block/Cart/Sidebar.php file with the code snippet given below:

<?php
namespace Kiwicommerce\Shippingbar\Block\Cart;

use Magento\Framework\View\Element\Template;

class Sidebar extends Template
{
   /**
    * @var \Kiwicommerce\Jobs\Helper\Data
    */
   private $helper;

   /**
    * Sidebar constructor.
    * @param Template\Context $context
    * @param \Kiwicommerce\Jobs\Helper\Data $helper
    * @param array $data
    */
   public function __construct(
       Template\Context $context,
       \Kiwicommerce\Shippingbar\Helper\Data $helper,
       array $data = []
   ) {
       parent::__construct($context, $data);
       $this->helper = $helper;
   }

   public function getConfigForShippingBar()
   {
       return $this->helper->getPriceForShippingBar();
   }
}
  1. Assign shipping bar config value to the jsLayout component

Add the following code in the app/code/Kiwicommerce/Shippingbar/view/frontend/template/cart/minicart.phtml file to assign the config value to the javascript variable.

<script>
   maxpriceShipping = <?= /* @escapeNotVerified */ $this->getConfigForShippingBar() ?>;
</script>

Now, your current file will look like this,

<div id="cart-page">
   <div id="block-cart-list" data-bind="scope:'minicart-addons'" class="block">
       <!-- ko template: getTemplate() --><!-- /ko -->
       <script>
           maxpriceShipping = <?= /* @escapeNotVerified */ $this->getConfigForShippingBar() ?>;
       </script>
       <script type="text/x-magento-init">
         {
             "#block-cart-list": {
                 "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
             },
             "*": {
                 "Magento_Ui/js/block-loader": "<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-1.gif') ?>"
             }
         }
     </script>
   </div>
</div>

Modify your js component file with the following content:

app/code/Kiwicommerce/Shippingbar/view/frontend/web/js/view/minicartaddons.js

Replace the following line of code:
var maxPrice = 100;

With the code given below:
var maxPrice = maxpriceShipping;

Happy coding! 🙂

4 Comments
  • Avatar for Sanne
    Sanne
    Posted at 08:06h, 23 October Reply

    Do you maybe have a git with the code? I’m stuck at step 7, the shippingbar won’t appair 🙁
    Thank you.

    • Avatar for KiwiCommerce
      KiwiCommerce
      Posted at 04:39h, 02 November Reply

      Hello, Is it possible for you to go through all the steps then check again? Make sure about a module is enabled, clear the cache and deploy static content after that. Hope this helps!

  • Avatar for a
    a
    Posted at 03:06h, 26 June Reply

    how to currency free shipping.
    thank you and best regard.

  • Avatar for Michael
    Michael
    Posted at 04:19h, 17 September Reply

    thank you very much, but how can I move free shipping bar to before “View and Edit Cart” link.

Leave a Reply

Your email address will not be published. Required fields are marked *