Question

I have a relatively stock minicart implementation, and I wanted to know if there is a configuration option or some other way of setting up the mini cart to drop down (open) when an item is successfully added to your cart on the frontend

Current behavior is the item count updates, but the minicart dropdown stays closed. Thanks!

Was it helpful?

Solution

For Magento 2

Pop up minicart when I add a product to the cart magento 2

I'm referring to Open header cart when product added to cart & https://stackoverflow.com/questions/13841390/toggle-dropdown-mini-cart-when-product-added-to-basket which are in Magento 1.

In Magento 2 we can create Event Observer for this

app\code\Custom\Module\etc\frontend\events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_predispatch_checkout_cart_add">
        <observer name="open_mini_cart" instance="Custom\Module\Observer\OpenMiniCartObserver" />
    </event>
</config>

app\code\Custom\Module\Observer\OpenMiniCartObserver.php

namespace Custom\Module\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;

class OpenMiniCartObserver implements ObserverInterface {

    protected $_urlManager;
    protected $redirect;

    public function __construct(
\Magento\Framework\UrlInterface $urlManager, \Magento\Framework\App\Response\RedirectInterface $redirect
) {
        $this->_urlManager = $urlManager;
        $this->redirect = $redirect;
    }

 public function execute(\Magento\Framework\Event\Observer $observer) {

    $actionName = $observer->getEvent()->getRequest()->getFullActionName();
    $controller = $observer->getControllerAction();
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();

    $cartUpdated = $objectManager->get('Magento\Checkout\Model\Session')->getCartWasUpdated(false);

    if ($cartUpdated) {
        // open mini cart
    }
    $this->redirect->redirect($controller->getResponse(), $this->redirect->getRefererUrl());
}

Still Some JS Stuff missing

OTHER TIPS

It can be done by simply modifying minicart.js file.

Navigate to vendor/magento/Magento_Checkout/view/web/js/view/minicart.js

Create override of the file by copy it in your theme folder.

Under initialize: function, you will see

$('[data-block="minicart"]').on('contentLoading', function (event) {

Replace the function with this code.

$('[data-block="minicart"]').on('contentLoading', function (event) {
            addToCartCalls++;
            self.isLoading(true);
            $('[data-block="minicart"]').on('contentUpdated', function ()  {
                $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("open");

                setTimeout(function() {
                    $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("close");
                }, 4000);
            });
        });

You can change the timeout as per your requirement.

upload the file and clean cache by running the command

php bin/magento cache:clean

Cheers!

Ajendra Panwar's answer is good but i wanted to point out that you can do this exact same thing without having to override the whole mini cart JS file. Doing this override can lead to upgrade problems, and since you just have to hook into the same functionality that it's using, the override is unnecessary. I made the call to Js file in my override of the header.phtml but this can go in any phtml file that is loaded on every page of the site:

app/design/frontend/{namespace}/{theme}/Magento_Theme/templates/html/header.phtml

...
<script type="text/x-magento-init">
{
    "*": {
        "Magento_Theme/js/mini-cart-action": {}
    }
}
</script>
...

And then create a JS file for our code:

app/design/frontend/{namespace}/{theme}/Magento_Theme/web/js/mini-cart-action.js

define([
    'jquery'
], function ($) {
    return function () {
        $('[data-block="minicart"]').on('contentLoading', function () {
            $('[data-block="minicart"]').on('contentUpdated', function ()  {
                $('html, body').animate({ scrollTop: 0 }, 'slow');
                $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("open");
            });
        });
    }
});

Be sure to clear your cache and redeploy so your JS file is in the pub folder. To make sure the file is loading correctly, you can look in the network tap of any page on the site:

enter image description here

Please add it to your file where its being called on every page: Note:This will also work with AJAX add to cart.

<script type="text/javascript">
require(['jquery', 'jquery/ui'], function($){
    jQuery(document).ready(minicartOpenClose);
    function minicartOpenClose () {
        if($('.message-success').is(':visible') && ($('.counter-number').text() > 0)){
            var successMsg = $('.message-success').text();
            var msgOne = "been added to shopping cart";
            var msgTwo = "to your shopping cart";
            if(successMsg.includes(msgOne) || successMsg.includes(msgTwo)){
                $('.action.showcart').trigger("click");
                setTimeout(function(){
                    if($('.action.showcart').hasClass('active')){
                        $('.action.showcart').trigger("click");
                    }
                }, 7000); 
            }
        } else {
            setTimeout(minicartOpenClose, 50);
        }
    }
});

In the years since i posted my first answer, i have found a better way to do this that utilizes Magento's Require JS mixin utility. This is much more streamline and works better with long term site updates.

You can create a mixin in your require.js config file:

app/design/frontend/{{vendor_name}}/theme/requirejs-config.js

let config = {
    config: {
        mixins: {
            'Magento_Catalog/js/catalog-add-to-cart': {
                'Magento_Catalog/js/catalog-add-to-cart-mixin': true
            }
        }
    }
};

This will act as an injector to the original file. No file override, no coping code, no risk when you go and update Magento. You can read more on mixins here: https://alanstorm.com/the-curious-case-of-magento-2-mixins/

Create the mixin file and add this:

app/design/frontend/{{vendor_name}}/theme/Magento_Catalog/web/js/catalog-add-to-cart-mixin.js

define([
    'jquery'
], function($) {
    "use strict";
    return function (widget) {
        $.widget('mage.catalogAddToCart', widget, {
            /**
             * Handler for the form 'submit' event
             *
             * @param {Object} form
             */
            submitForm: function (form) {
                this.showCart();
                this.ajaxSubmit(form);
            },
            /**
             * Open minicart when Add To Cart has been clicked
             */
            showCart: function() {
                let self = this;
                $('.block-minicart').dropdownDialog('open');
                $(this.options.dropdownDialogSelector).addClass('minicart-loading');
                $(this.options.minicartSelector).on('contentUpdated', function () {
                    $(self.options.dropdownDialogSelector).removeClass('minicart-loading');
                });
            }
        });
        return $.mage.catalogAddToCart;
    }
});

Inside this file you have created an injector into the original file and the return that with your added code with return $.mage.catalogAddToCart;. I found it is required that you include submitForm() to get this working. Without it I found the add to cart button wouldn't enable on the product page. Inside that function call, you can place any custom call you like, in our case we are just calling showCart() which opens the minicart for us when add to cart is clicked.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top