12

How can you add an "Empty Cart" button to the minicart in Magento 2.

enter image description here

Is it possible with layout xml?

2 Answers 2

17

I have just created a proper module for your question:

We need to declare the custom js component and html template:

app/code/Vendor/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>
        <referenceBlock name="minicart">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="types" xsi:type="array"/>
                    <item name="components" xsi:type="array">
                        <item name="minicart_content" xsi:type="array">
                            <item name="component" xsi:type="string">Vendor_MiniCart/js/view/minicart</item>
                            <item name="config" xsi:type="array">
                                <item name="template" xsi:type="string">Vendor_MiniCart/minicart/content</item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

app/code/Vendor/MiniCart/view/frontend/web/js/view/minicart.js

   define([
    'jquery',
    'Magento_Checkout/js/view/minicart',
    'Magento_Ui/js/modal/alert',
    'Magento_Ui/js/modal/confirm'
], function ($ ,Component, alert, confirm) {
    'use strict';

    return Component.extend({
        confirmMessage: $.mage.__('Are you sure you would like to remove all items from the shopping cart?'),
        emptyCartUrl: window.checkout.emptyMiniCart,

        emptyCartAction: function (element) {
            var self = this,
                href = self.emptyCartUrl;
            $(element).on('click', function () {
                var el = this;
                confirm({
                    content: self.confirmMessage,
                    actions: {
                        confirm: function () {
                            self._removeAllItems(href, el);
                        },
                        always: function (event) {
                            event.stopImmediatePropagation();
                        }
                    }
                });
            });
        },

        _removeAllItems: function (href, elem) {
            $.ajax({
                url: href,
                type: 'post',
                dataType: 'json',
                beforeSend: function () {
                    $(elem).attr('disabled', 'disabled');
                },
                complete: function () {
                    $(elem).attr('disabled', null);
                }

            }).done(function (response) {
                if (!response.errors) {

                } else {
                    var msg = response.message;

                    if (msg) {
                        alert({
                            content: msg
                        });
                    }
                }
            }).fail(function (error) {
                console.log(JSON.stringify(error));
            });
        }
    });
});

emptyCartUrl: window.checkout.emptyMiniCart, we will get the empty link from checkout config: app/code/Vendor/MiniCart/Plugin/Cart/ConfigPlugin.php (declare later).

We need to copy the minicart content from the original file: vendor/magento/module-checkout/view/frontend/web/template/minicart/content.html. And then, in our custom file, we need to add the action text:

app/code/Vendor/MiniCart/view/frontend/web/template/minicart/content.html

 <!-- ko if: getCartParam('summary_count') -->
    <div class="actions">
        <div class="secondary">
            <a class="action empty-cart" id="empty-minicart" data-bind="afterRender: emptyCartAction">
                <span><!-- ko i18n: 'Empty Cart Now' --><!-- /ko --></span>
            </a>
        </div>
    </div>
 <!-- /ko -->

Declare DI to add the empty link to checkout config:

app/code/Vendor/MiniCart/etc/frontend/di.xml

<?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\Block\Cart\Sidebar">
        <plugin name="empty_cart_url" type="Vendor\MiniCart\Plugin\Cart\ConfigPlugin" sortOrder="20" />
    </type>
</config>

app/code/Vendor/MiniCart/Plugin/Cart/ConfigPlugin.php

<?php

namespace Vendor\MiniCart\Plugin\Cart;

use Magento\Framework\UrlInterface;

class ConfigPlugin
{
    /**
     * @var UrlInterface
     */
    protected $url;

    /**
     * ConfigPlugin constructor.
     * @param UrlInterface $url
     */
    public function __construct(
        UrlInterface $url
    ) {
        $this->url = $url;
    }

    /**
     * @param \Magento\Checkout\Block\Cart\Sidebar $subject
     * @param array $result
     * @return array
     */
    public function afterGetConfig(
        \Magento\Checkout\Block\Cart\Sidebar $subject,
        array $result
    ) {
        $result['emptyMiniCart'] = $this->url->getUrl('minicart/cart/emptycart');
        return $result;
    }
}

Now, we need to build the controller:

app/code/Vendor/MiniCart/etc/frontend/routes.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="minicart" frontName="minicart">
            <module name="Vendor_MiniCart" />
        </route>
    </router>
</config>

app/code/Vendor/MiniCart/Controller/Cart/EmptyCart.php

<?php

namespace Vendor\MiniCart\Controller\Cart;

use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Json\Helper\Data;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Checkout\Model\Session;
use Psr\Log\LoggerInterface;

class EmptyCart extends Action
{
    /**
     * @var Session
     */
    protected $checkoutSession;

    /**
     * @var JsonFactory
     */
    protected $jsonFactory;

    /**
     * @var Data
     */
    protected $jsonHelper;

    /**
     * @var LoggerInterface
     */
    protected $logger;

    /**
     * @var Magento\Checkout\Model\Cart
     */
    protected $cart;

    /**
     * EmptyCart constructor.
     *
     * @param Context $context
     * @param Session $session
     * @param JsonFactory $jsonFactory
     * @param Data $jsonHelper
     * @param LoggerInterface $logger
     */
    public function __construct(
        Context $context,
        Session $session,
        JsonFactory $jsonFactory,
        Data $jsonHelper,
        LoggerInterface $logger,
        \Magento\Checkout\Model\Cart $cart
    ) {
        $this->checkoutSession = $session;
        $this->jsonFactory = $jsonFactory;
        $this->jsonHelper = $jsonHelper;
        $this->logger = $logger;
        $this->cart = $cart;
        parent::__construct($context);
    }

    /**
     * Ajax execute
     *
     */
    public function execute()
    {
        $response = [
            'errors' => false
        ];

        if ($this->getRequest()->isAjax()) {
            try {
                $this->cart->truncate()->save();
                $response['message'] = __('Empty Cart.');

            } catch (\Exception $e) {
                $response = [
                    'errors' => true,
                    'message' => __('Some thing went wrong.')
                ];
                $this->logger->critical($e);
            }
        } else {
            $response = [
                'errors' => true,
                'message' => __('Need to access via Ajax.')
            ];
        }
        /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
        $resultJson = $this->jsonFactory->create();
        return $resultJson->setData($response);
    }
}

Need to reload cart section:

app/code/Vendor/MiniCart/etc/frontend/sections.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
    <action name="minicart/cart/empty">
        <section name="cart"/>
    </action>
</config>

Remember to create registration.php and module.xml

app/code/Vendor/MiniCart/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_MiniCart',
    __DIR__
);

app/code/Vendor/MiniCart/etc/module.xml

<?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="Vendor_MiniCart" setup_version="1.0.0"/>
</config>

[IMAGES DEMO]

Mini Cart:

enter image description here

Message Confirmation:

enter image description here

11
  • Thanks for such detailed and complete solution! It worked, except code to empty cart. To make it work on 2.1.10 I've had to change it a bit pastebin.com/sYmhqYRL
    – Viperet
    Commented Dec 14, 2017 at 10:45
  • 2
    And even a bit shorter pastebin.com/2tMEMdeA
    – Viperet
    Commented Dec 14, 2017 at 11:23
  • 1
    @Viperet I agree with you. Should use $this->cart->truncate()->save();. Feel free to edit my answer. Commented Dec 14, 2017 at 11:54
  • @KhoaTruongDinh mini cart showing only "Empty Cart Now" button after implementing above code. Any solution?
    – Vishal
    Commented Jan 12, 2018 at 13:51
  • 1
    My Magento version is 2.2.6. Can you please help me? Commented Jan 23, 2019 at 7:23
0

I have made repo for this extension.

I have test it before I make the repo it's working on Magento 2.4

https://github.com/itc4u/empty-minicart

Regards,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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