6

How to show tax and shipping costs in mini cart popup in Magento 2?

enter image description here

  • Which is your Magento version? – Khoa TruongDinh Jan 9 '17 at 16:34
  • I'm on Magento 2, 2.1.2 to be exact. – nuwaus Jan 9 '17 at 16:36
6

To show additional stuff or costs in the minicart (like taxes or shipping costs), you need to understand where the data in the minicart comes from.

The Customer Data Section Pool

If you add a product to the cart, you can see in your inspector a XHR request is made to /customer/section/load with the arguments ?sections=cart,messages. This controller checks in the section pool (Magento\Customer\CustomerData\SectionPoolInterface) for objects that provide data for the required sections. This data is saved in the local storage of your browser and utilized in the minicart. This design pattern is called an Object Pool and they are used thoroughly in Magento 2.

You can hook into this Object Pool very easily by adding the following to your modules' di.xml:

<type name="Magento\Customer\CustomerData\SectionPoolInterface">
    <arguments>
        <argument name="sectionSourceMap" xsi:type="array">
            <item name="my-section" xsi:type="string">Vendor\Module\CustomerData\Something</item>
        </argument>
    </arguments>
</type>

As for the Something-class in this example: the only requirement is that it implements \Magento\Customer\CustomerData\SectionSourceInterface so it has the getSectionData()-method. This method should return an array with data that is added to the JSON object when you ask the controller to load it (for example: /customer/section/load?sections=my-section.

Extending existing functionality

Now as for your question the answer is even simpler: since you want to add some extra quote information (like taxes and shipping costs) you can simply use a plugin to hook into Magento\Checkout\CustomerData\Cart::getSectionData() to add your information to the data that is fetched when /customer/section/load?sections=cart is called. In your di.xml add:

<type name="Magento\Checkout\CustomerData\Cart">
    <plugin name="my_custom_stuff" type="Vendor\Module\Plugin\Magento\Checkout\CustomerData\Cart"/>
</type>

And in your plugin:

/**
 * @param \Magento\Checkout\CustomerData\Cart $subject
 * @param array $result
 * @return array
 */
public function afterGetSectionData(\Magento\Checkout\CustomerData\Cart $subject, array $result)
{
    $result['something'] = 'Stuff';
    return $result;
}

Now what you do in your plugin is beyond the scope of this help, so you have to figure out on your own how to fetch the Tax and/or shipping costs at this point, but I'm pretty sure you'll figure that out.

Implementing it in the Frontend

Now we have a hook where we can add data from the backend to the frontend. Please note that this is only executed when the customer section data is loaded! or even better: as soon as you add a product to the cart. In other words: you won't have this data on the frontend without updating your cart first.

Now, the data in our plugin is added to our cart-node in the JSON, and we can access this in the Magento_Checkout/js/view/checkout/minicart/subtotal/totals UI Component. This has a property called cart which is an observable that contains everything from our JSON response. This becomes very clear if you look at the template Magento_Checkout/minicart/subtotal/totals.html:

<div class="amount">
    <span data-bind="html: cart().subtotal"></span>
</div>

In this file, cart().subtotal reflects that cart.subtotal-item in the JSON data.

Adding an extra rule to the minicart

Now here comes the most important part (and probably the answer to your question): How can we show our extra data in the minicart?

Well the minicart is made up of a bunch of UI Components tangled into each other, so without too much further explanation this is how you set it up. Add checkout_cart_sidebar_total_renderers.xml to your modules' frontend/layout-folder:

<?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="subtotal.container" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <!--
                                            Include stuff in MiniCart:
                                        -->
                                        <item name="stuff" xsi:type="array">
                                            <item name="component" xsi:type="string">uiComponent</item>
                                            <item name="config" xsi:type="array">
                                                <item name="template" xsi:type="string">Vendor_Module/checkout/minicart/stuff</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">Vendor_Module/checkout/minicart/stuff/totals</item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

And the template frontend/web/checkout/minicart/stuff.html:

<div class="my-stuff">
    <span class="label">
        <!-- ko i18n: 'My Custom Stuff' --><!-- /ko -->
    </span>

    <!-- ko foreach: elems -->
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!-- /ko -->
</div>

And the template frontend/web/checkout/minicart/stuff/totals.html:

<div class="amount price-container">
    <span class="price-wrapper" data-bind="html: cart().something"></span>
</div>

This should do the trick. Haven't tested this example, but it's taken from an implementation I did where I need to add the FPT, Shipping costs and Grand Total to the minicart and it worked like a charm!

It's so easy! ;-)

  • Thanks, it works! I really did not know that it is SO easy ;-) – bpoiss Feb 13 '18 at 11:41
  • Hi How do i get tax here. – Hitesh Agrawal Oct 16 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.