5

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!

1
  • Hi @Pat Welcome to Magento SE
    – Jackson
    Oct 19, 2016 at 3:02

6 Answers 6

4

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

2
  • So I'm not sure the event aspects are really necessary, but the first link you provided had the js component that did the trick, thanks!
    – Pat Marx
    Oct 19, 2016 at 18:50
  • Wow Great @PatMarx Good to Hear that :)
    – Jackson
    Oct 20, 2016 at 1:19
13

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!

4
  • I wouldn't recommend editing the vendor files... make the update in your theme Jan 27, 2018 at 12:27
  • Yes i missed to mention the override of file, updated the answer :) Feb 1, 2018 at 13:40
  • i tested but it's not working. Jun 6, 2019 at 8:41
  • This won't work with login customers add wishlist items to their cart. I have posted answer which worked for me on every pages. Jul 8, 2019 at 11:33
4

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

2
  • 1
    This is a good answer Nov 8, 2020 at 20:01
  • I have noticed that when animating the scroll, there is issues with click events on the page. I haven't debugged this all the way, but it might be best to remove that if there are click event issues when you use it.
    – circlesix
    Nov 16, 2020 at 22:19
2

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);
        }
    }
});

1

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.

1

A simple solution is here: https://webarchers.com/popup-minicart-when-product-add-to-the-cart-magento-2/

     require(['jquery'], function ($) {
            $(document).on('click','.tocart',function(event){
            // console.log("incopyright")
            var minicart = $('[data-block="minicart"]');
            setTimeout(function() {
                minicart.find('[data-role="dropdownDialog"]').dropdownDialog('open');
            }, 3000);
            setTimeout(function() {
                minicart.find('[data-role="dropdownDialog"]').dropdownDialog('close');
            }, 10000);
             
            event.stopPropagation();
        });
});
</script>

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