0

I currently have my subtotal tax settings set to 'Display subtotal excluding tax'. This has changed the subtotal in the minicart to display the subtotal excluding tax.

enter image description here

How can I display the grand total of the order including tax in the highlighted area with the settings mentioned above?

1
  • Did you reach an answer for this? Grand total would include shipping? – Dominic Xigen May 22 '19 at 21:24
2

This may be late, but I would post this for the people who reach here in future.

Let's start with the layout.xml [scope]/[module]/view/frontend/layout/default.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
    <referenceContainer name="content">
        <block class="Magento\Checkout\Block\Onepage" name="common.checkout.config"
               template="[scope]_[module]::checkout/config.phtml" cacheable="false">
        </block>
    </referenceContainer>
    <referenceBlock name="minicart">
        <arguments>
            <argument name="jsLayout" xsi:type="array">
                <item name="components" xsi:type="array">
                    <item name="grand-total" xsi:type="array">
                        <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/grand-total</item>
                        <item name="displayArea" xsi:type="string">totals</item>
                        <item name="config" xsi:type="array">
                            <item name="title" xsi:type="string" translate="true">Total Cost with GST</item>
                            <item name="template" xsi:type="string">Magento_Checkout/cart/totals/grand-total</item>
                        </item>
                    </item>
                </item>
            </argument>
        </arguments>
    </referenceBlock>
</body>

I am not sure if it is a good idea to place cacheable="false" block in a default.xml, Better to try without it and thoroughly test.

Override the and add getQuote Method. [scope]/[module]/etc/frontend/di.xml

<preference for="Magento\Checkout\Block\Onepage" type="IWD\Opc\Block\Onepage" />

app/code/[scope]/[module]/Block/Onepage.php

namespace [scope]\[module]\Block;

use Magento\Checkout\Block\Onepage as CheckoutOnepage;
use Magento\Checkout\Model\Session\Proxy as CheckoutSession;
use Magento\Framework\View\Element\Template\Context;
use Magento\Framework\Data\Form\FormKey;
use Magento\Checkout\Model\CompositeConfigProvider;

class Onepage extends CheckoutOnepage
{

    public $checkoutSession;
    public $quote = null;

    public function __construct(
        Context $context,
        FormKey $formKey,
        CompositeConfigProvider $configProvider,
        CheckoutSession $checkoutSession,
        array $layoutProcessors = [],
        array $data = []
    ) {
        $this->checkoutSession = $checkoutSession;
        parent::__construct($context, $formKey, $configProvider, $layoutProcessors, $data);
    }

    public function getQuote()
    {
        if (null === $this->quote) {
            $this->quote = $this->checkoutSession->getQuote();
        }

        return $this->quote;
    }
}

[scope]/[module]/view/frontend/templates/checkout/config.phtml

Those who need the explanation, why below two code blocks are needed please check at the end of the post.

<?php if($block->getQuote() && $block->getQuote()->getId()):?>
<script>
window.checkoutConfig = <?= /* @escapeNotVerified */ $block->getSerializedCheckoutConfig() ?>;
// Create aliases for customer.js model from customer module
window.isCustomerLoggedIn = window.checkoutConfig.isCustomerLoggedIn;
window.customerData = window.checkoutConfig.customerData;
</script>
<?php endif;?>

In [scope]/[module]/view/frontend/layout/checkout_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
  <body>
    <referenceBlock name="common.checkout.config" remove="true"/>
  </body>
</page>

Finaly let's add them to the mini-cart app/design/frontend/[package]/[theme]/[scope]_[module]/templates/cart/minicart.phtml

<div id="grand-total" class="grand-total" data-bind="scope:'grand-total'">
                <!-- ko template: getTemplate() --><!-- /ko -->
</div>

<script type="text/x-magento-init">
        {
            "#grand-total": {
                "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout() ?>
            }
        }
</script>

The explanation for adding window.checkoutConfig

When loading vendor/magento/module-checkout/view/frontend/web/js/view/summary/grand-total.js (By Magento_Checkout/js/view/summary/grand-total entry in the default.xml layout file ), It also tries to load the vendor/magento/module-checkout/view/frontend/web/js/model/quote.js (By the 'Magento_Checkout/js/model/quote' in the requireJs define array). However, when loading the quote.js it tries to access certain data in the window.checkoutConfig. This is not available in the pages except checkout control actions. So we have to manually place this on every page with the help of default.xml.

I don't agree with this Magento core implementation as I believe, this should be implemented with the use of customerData with the local storage. You may find more details regarding the issue with this Magento Core approach, in this article by Jisse Reitsma

2
  • why we removed the block from checkout_index_index.xml ? – 26vivek May 4 at 14:36
  • Because the same block added to the content area in [scope]/[module]/view/frontend/layout/default.xml, This is to avoid having duplicate sections. <referenceContainer name="content"> <block class="Magento\Checkout\Block\Onepage" name="common.checkout.config" template="[scope]_[module]::checkout/config.phtml" cacheable="false"> </block> </referenceContainer> – MudithaE May 5 at 15:54
0

Not tested, just an idea

You could extend module-checkout/view/frontend/layout/default.xml & replace subtotal (or create a new) component with your needings

<item name="subtotal.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">uiComponent</item>
            <item name="config" xsi:type="array">
                <item name="template" xsi:type="string">Magento_Checkout/minicart/subtotal</item>
            </item>
        </item>
    </item>
</item>

More info about uiComponents http://devdocs.magento.com/guides/v2.1/ui_comp_guide/concepts/ui_comp_xmldeclaration_concept.html

An alternate, and easier, way if you are not comfortable with UI Components (easy!) would be deleting that component in your layout extend & then just print your wanted value in Magento_Checkout::cart/minicart.phtml template (overwriting the template in your custom theme, of course)

<?php echo $block->getQuote()->getGrandTotal(); ?>

This should work, as \Magento\Checkout\Block\Cart\Sidebar (which is the associated block of minicart template) extends \Magento\Checkout\Block\Cart\AbstractCart, which provides getQuote() method

0

This is pretty old, but I'm going to leave my solution in here also.
The idea is to display the grand total in the minicart in the same way the subtotal is displayed.

Let's make a new module called Easylife_Checkout with these files

registration.php

<?php

declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Easylife_Checkout', __DIR__);

composer.json

{
    "name": "easylife/module-checkout",
    "description": "Display the grand total in minicart",
    "type": "magento2-module",
    "license": "MIT",
    "minimum-stability": "dev",
    "require": {
        "magento/framework": "*",
        "magento/module-checkout": "*",
        "php": "~7.1.3||~7.2.0||~7.3.0"
    },
    "autoload": {
        "psr-4": {
            "Easylife\\Checkout\\": ""
        },
        "files": [
            "registration.php"
        ]
    }
}

README.md - explain here what the module does - you can even link to this answer :).

etc/module.xml - the module sequence file

<?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="Easylife_Checkout">
        <sequence>
            <module name="Magento_Checkout"/>
        </sequence>
    </module>
</config>

So far so good

The problem is that you don't have the grand total available in the data source that returns the subtotal, Magento\Checkout\CustomerData\Cart class.
So let's add it via a plugin

etc/di.xml - dependency injection file where we declare the 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="get-grand-total" type="Easylife\Checkout\Plugin\CustomerData\CartPlugin" />
    </type>
</config>

Plugin/CustomerData/CartPlugin.php - the actual plugin. this makes the grand total available in the minicart data source

<?php

declare(strict_types=1);

namespace Easylife\Checkout\Plugin\CustomerData;

use Magento\Checkout\CustomerData\Cart;
use Magento\Checkout\Helper\Data as CheckoutHelper;
use Magento\Checkout\Model\Session;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Quote\Model\Quote;

class CartPlugin
{
    /**
     * @var Session
     */
    private $checkoutSession;
    /**
     * @var CheckoutHelper
     */
    private $checkoutHelper;
    /**
     * @var Quote
     */
    private $quote;

    /**
     * CartPlugin constructor.
     * @param Session $checkoutSession
     * @param CheckoutHelper $checkoutHelper
     */
    public function __construct(Session $checkoutSession, CheckoutHelper $checkoutHelper)
    {
        $this->checkoutSession = $checkoutSession;
        $this->checkoutHelper = $checkoutHelper;
    }

    /**
     * @param Cart $subject
     * @param array $data
     * @return array
     * @throws LocalizedException
     * @throws NoSuchEntityException
     */
    public function afterGetSectionData(Cart $subject, array $data)
    {
        $totals = $this->getQuote()->getTotals();
        $data['grandTotalAmount'] = $totals['grand_total'] ? $totals['grand_total']->getData('value') : null;
        $data['grandTotal'] = $data['grandTotalAmount']
            ? $this->checkoutHelper->formatPrice($data['grandTotalAmount'])
            : 0;
        return $data;
    }

    /**
     * @return Quote
     * @throws LocalizedException
     * @throws NoSuchEntityException
     */
    private function getQuote()
    {
        if (null === $this->quote) {
            $this->quote = $this->checkoutSession->getQuote();
        }
        return $this->quote;
    }
}

now we need a KO template to display the grand total.

view/frontend/web/template/minicart/grand-total.html

<div class="grand-total">
    <span class="label">
        <!-- ko i18n: 'Order Total' -->
        <!-- /ko -->
    </span>
    <div class="amount price-container">
        <span class="price-wrapper" data-bind="html: cart().grandTotal"></span>
    </div>
</div>

We don't need js component to render this template because we can use the same component that displays subtotal

Now let's add that component to the minicart.

view/frontend/layout/default.xml

<?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>
        <referenceContainer name="header-wrapper">
            <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">
                                            <item name="grand-total" 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">Easylife_Checkout/minicart/grand-total</item>
                                                </item>
                                            </item>
                                            <item name="subtotal"><!-- This will remove the subtotal. You can remove this if you want to keep it -->
                                                <item name="config" xsi:type="array">
                                                    <item name="componentDisabled" xsi:type="boolean">true</item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </argument>
                </arguments>
            </referenceBlock>
        </referenceContainer>
    </body>
</page>

Do the usual bin/magento setup:upgrade to install the module bin/magento setup:static-content deploy -f to deploy the static resource. That's it.

2
  • getting this error after following all above steps. Element 'item': The type definition is abstract. – Vaibhav Ahalpara Nov 20 '20 at 14:45
  • 1
    try replacing <item name="subtotal"> with <item name="subtotal" xsi:type="array"> – Marius Nov 20 '20 at 15:30

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.