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.
- 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
- 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__ );
- 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
- 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>
- 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.
- 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: '
- 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:
- 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>
- 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.
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.
- 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 ); } }
- 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(); } }
- 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! ?
+ 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;
}
});
});
- 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
Include miniprogress.less file in the <head> element before the <body> element at default.xml layout file by adding the following content:
The Free Shipping Bar has now been added in your mini-cart and you can see it in the screenshot below:
- 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
- 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
By making the above changes in the file, you will see that the configuration menu will appear at the store > configuration menu.
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.
- 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
- 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:
- 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.
Now, your current file will look like this,
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! ?
Do you maybe have a git with the code? I’m stuck at step 7, the shippingbar won’t appair 🙁
Thank you.
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!
Did you get solution?
Hey Sanne (and anyone else frustrated by this), the directory should be named ‘templates’. Not the singular ‘template’.
Incorrect in tutorial–> app/code/Kiwicommerce/Shippingbar/view/frontend/template/cart/minicart.phtml
Should be this–> app/code/Kiwicommerce/Shippingbar/view/frontend/templates/cart/minicart.phtml
I went through the tutorial carefully three times and it never worked. Then the above is what fixed it for me.
Oh, and then be sure to run these (I ran this in production mode);
php bin/magento module:enable Kiwicommerce_Shippingbar
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
That should do it. Hope this helps someone.
how to currency free shipping.
thank you and best regard.
thank you very much, but how can I move free shipping bar to before “View and Edit Cart” link.
tҺe website іѕ really good, I really like your website!
First time visiting your website, I like your blog!
tҺe website іѕ really good, I love your website!
I am using this solution but this is not working for me. I have tried everything but the progress bar is showing but blank only. Could anyone help me?