Adding a new field to the mini cart in Magento 2
In this tutorial, we will add a new field "Discount" to the mini cart. That is, if the customer got a discount in his cart, he would now be able to see it in the mini cart.
For example, we created a cart rule that applies a 10% discount on bags.
Here is how the current mini cart looks like with the cart rule applied -
You can see that the discount doesn’t show up in the mini cart, even though it was applied in the cart -
And here is how it will look after our changes -
So let’s go ahead and create our module.
Step 1: Create the basic file structure for your module
Here is how our module’s file structure will look like -
Create the folder app/code/Myvendor/Mymodule and add the following files:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Myvendor_Mymodule" setup_version="1.0.0" />
</config>
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Myvendor_Mymodule',
__DIR__
);
Now when you have the basic module structure, lets proceed to the actual files that will add the "Discount" field to the mini cart.
Step 2: Add the new minicart field to the layout xml file and create the template files
<?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="minicart">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="minicart_content" xsi:type="array">
<item name="children" xsi:type="array">
<item name="discount.container" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="config" xsi:type="array">
<item name="displayArea" xsi:type="string">subtotalContainer</item>
</item>
<item name="children" xsi:type="array">
<item name="subtotal" xsi:type="array">
<item name="component" xsi:type="string">Magento_Checkout/js/view/checkout/minicart/subtotal/totals</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">Myvendor_Mymodule/minicart/discount</item>
</item>
<item name="children" xsi:type="array">
<item name="subtotal.totals" xsi:type="array">
<item name="component" xsi:type="string">Magento_Checkout/js/view/checkout/minicart/subtotal/totals</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">Myvendor_Mymodule/minicart/discount/inner</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
This file tells Magento to add the “Discount” as a child in the minicart and sets our template files to it. Now let's add the template files.
<!-- ko if: (cart().discount_amount_no_html < 0) -->
<div class="subtotal">
<span class="label">
<!-- ko i18n: 'Discount' --><!-- /ko -->
</span>
<!-- ko foreach: elems -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
</div>
<!-- /ko -->
<!-- ko if: (cart().discount_amount_no_html < 0) -->
<div class="amount price-container">
<span class="price-wrapper" data-bind="html: cart().discount_amount"></span>
</div>
Step 3: Provide the value of the new field to be fetched on the frontend
Now the only thing left to do is to provide the value of the “Discount” field to the class \Magento\Checkout\CustomerData\Cart that will be fetched by the minicart on the frontend. To do that, we will use a plugin.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\CustomerData\Cart">
<plugin name="cartPrivateDataDiscount" type="Myvendor\Mymodule\Plugin\Checkout\CustomerData\Cart"/>
</type>
</config>
<?php
namespace Myvendor\Mymodule\Plugin\Checkout\CustomerData;
class Cart
{
protected $checkoutSession;
protected $checkoutHelper;
protected $quote;
public function __construct(
\Magento\Checkout\Model\Session $checkoutSession,
\Magento\Checkout\Helper\Data $checkoutHelper
) {
$this->checkoutSession = $checkoutSession;
$this->checkoutHelper = $checkoutHelper;
}
/**
* Get active quote
*
* @return \Magento\Quote\Model\Quote
*/
protected function getQuote()
{
if (null === $this->quote) {
$this->quote = $this->checkoutSession->getQuote();
}
return $this->quote;
}
protected function getDiscountAmount()
{
$discountAmount = 0;
foreach($this->getQuote()->getAllVisibleItems() as $item){
$discountAmount += ($item->getDiscountAmount() ? $item->getDiscountAmount() : 0);
}
return $discountAmount;
}
public function afterGetSectionData(\Magento\Checkout\CustomerData\Cart $subject, $result)
{
$result['discount_amount_no_html'] = -$this->getDiscountAmount();
$result['discount_amount'] = $this->checkoutHelper->formatPrice(-$this->getDiscountAmount());
return $result;
}
}
Testing the module
Now it’s time to test our module.
First, create a cart rule that gives us a 10% discount on the product from the “Bags” category. Afterward, install the module by running the following commands in your SSH:
php bin/magento module:enable Myvendor_Mymodule --clear-static-content
php bin/magento setup:upgrade
If you running Magento on the default or a developer mode, run the following commands:
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush
Otherwise, if you running Magento on the production mode, run the following commands:
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy
php bin/magento cache:flush
Now try adding a bag to your cart. You should be able to see the discount line in the minicart -
Summing up
In this tutorial, we demonstrated how to add a new field to the mini cart.
Although Magento 2 is quite sophisticated to develop on, once you know how to do that, it is quite easy. Also, the implementations for features on Magento 2 are usually quite elegant because of Magento 2 sophisticated architecture.