12

How to hide notification messages like success message after adding product to cart or any error messages or notices after few seconds after they appear on the the frontend using knockout js.

Example : When I am adding a product in the cart, a success message appear saying "product has been added to your cart". I want to hide this success message after 5 seconds after it appear on the screen.

5 Answers 5

15

Try following way:

Vendor/Module/view/frontend/requirejs-config.js

var config = {
    "map": {
        "*": {
            "Magento_Theme/js/view/messages": "Vendor_Module/js/view/messages",
        }
    }
}

Vendor/Module/view/frontend/web/js/view/messages.js

define([
    'jquery',
    'uiComponent',
    'underscore',
    'Magento_Customer/js/customer-data',
    'jquery/jquery-storageapi'
], function ($, Component, _, customerData) {
    'use strict';

    return Component.extend({
        defaults: {
            cookieMessages: [],
            messages: []
        },

        /** @inheritdoc */
        initialize: function () {
            this._super();

            this.cookieMessages = $.cookieStorage.get('mage-messages');
            this.messages = customerData.get('messages').extend({
                disposableCustomerData: 'messages'
            });

            if (!_.isEmpty(this.messages().messages)) {
                customerData.set('messages', {});
            }

            $.cookieStorage.set('mage-messages', '');
            setTimeout(function() {
                $(".messages").hide('blind', {}, 500)
            }, 5000);
        }
    });
});

Clear cache.

12
  • I have tried and it is not showing any message at all. Jan 30, 2017 at 5:55
  • Delete pub/static/*, clear cache. Run setup:static-content:deploy.
    – Sohel Rana
    Jan 30, 2017 at 6:31
  • I have tried after cleaning the pub/static and executing the command setup:static-content:deploy , but still no effect. I have added alert in the initialize function but it is not alerting at all. I guess js file is not included properly. It would be great if you can share if anything else is required as well. Jan 30, 2017 at 7:33
  • For my case, I use SR_StackExchange is module name. And it's working fine with luma theme.
    – Sohel Rana
    Jan 30, 2017 at 7:50
  • 1
    I have checked on different machine and the code seems to be working. Thanks for your answer. One more thing that I want to know is, what is the purpose of parameters 'blind' and {} in hide function. Jan 30, 2017 at 8:58
4

Please try the below solution and it works for me and I hope it will also work for you.

Please add the below code in the requirejs-config.js file to override the message js file.

var config = {
    "map": {
        "*": {
            "Magento_Theme/js/view/messages": "Vendor_Module/js/view/messages",
        }
    }
}

Create a new message Js file in your module or you can also override directly by adding the same file in your theme directory.

Vendor/Module/view/frontend/web/js/view/messages.js

define([
    'jquery',
    'uiComponent',
    'Magento_Customer/js/customer-data',
    'underscore',
    'escaper',
    'jquery/jquery-storageapi'
], function ($, Component, customerData, _, escaper) {
    'use strict';

    return Component.extend({
        defaults: {
            cookieMessages: [],
            messages: [],
            allowedTags: ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a']
        },

        /**
         * Extends Component object by storage observable messages.
         */
        initialize: function () {
            this._super();

            this.cookieMessages = _.unique($.cookieStorage.get('mage-messages'), 'text');
            this.messages = customerData.get('messages').extend({
                disposableCustomerData: 'messages'
            });

            // Force to clean obsolete messages
            if (!_.isEmpty(this.messages().messages)) {
                customerData.set('messages', {});
            }

            $.cookieStorage.set('mage-messages', '');
            
        },

        /**
         * Prepare the given message to be rendered as HTML
         *
         * @param {String} message
         * @return {String}
         */
        prepareMessageForHtml: function (message) {
            $(".messages").show();
            setTimeout(function() {
                $(".messages").hide('blind', {}, 500)
            }, 5000);
            return escaper.escapeHtml(message, this.allowedTags);
        }
        
    });
});

I have tested this in 2.3.5 and it seems to be working fine.

Please let me know if you need more details. Thanks.

1

Try this way.

requirejs-config.js

var config = {
    config: {
        mixins: {
            'Magento_Theme/js/view/messages': {
                '[Your_Module]/js/view/messages-mixin': true
            }
        }
    }
};

messages-mixin.js

define([
    'underscore',
    'Magento_Customer/js/customer-data'
], function (_, customerData) {
    'use strict';

    var mixin = {
        initialize: function () {
            this._super();

            this.messages.subscribe(function (messages) {
                if (_.isEmpty(messages.messages)) {
                    return;
                }

                setTimeout(function () {
                    customerData.set('messages', {});
                }, 5000);
            });
        }
    };

    return function (target) {
        return target.extend(mixin);
    }
});
1
  • Thank you @rangerz. It is working in Magento 2.4.3, too. Dec 12, 2022 at 3:03
0

we can do it from js mixin

in you custom module view/frontend/requirejs-config.js

var config = {
config: {
        mixins: {
            'Magento_Ui/js/view/messages': {
                'NameSpace_Module/js/messages-mixin': true
            }
        }
    }
};

messages-mixin.js

 define([
        'jquery'
    ], function($) {
        'use strict';
        return function(targetModule) {
            return targetModule.extend({
                onHiddenChange: function (isHidden) {
                var self = this;

                // Hide message block if needed
    //            if (isHidden) {
    //                setTimeout(function () { 
    //                    $(self.selector).hide('blind', {}, 500);
    //                }, 30000);                
    //            }
                }
            });
        };

    });
0
0

Make a mixin as Kumar said but do not extend the Magento_Ui messages since those are for checkout etc but extend Magento_Theme messages.js. The full code is as follow.

requirejs-config.js

var config = {
    'config': {
        'mixins': {
            'Magento_Theme/js/view/messages': {
                'Bemeir_General/js/mixin/messages-mixin': true
            }
        }
    }
};

messages-mixin.js

define([
    'jquery',
    'uiComponent',
    'Magento_Customer/js/customer-data',
    'underscore',
    'jquery/jquery-storageapi'
], function ($, Component, customerData, _) {
    'use strict';
    return function (targetModule) {

        targetModule.defaults.isHidden = false;
        targetModule.defaults.listens.isHidden = 'onHiddenChange';
        targetModule.defaults.selector = '.page.messages .messages';

        return targetModule.extend({
            initialize: function () {
                let original = this._super();
                console.log(targetModule.defaults);
                return original;
            },
            initObservable: function () {
                this._super()
                    .observe('isHidden');

                return this;
            },

            isVisible: function () {
                return this.isHidden(!_.isEmpty(this.messages().messages) || !_.isEmpty(this.cookieMessages));
            },

            removeAll: function () {
                $(this.selector).find('.message').removeClass('show');
            },

            onHiddenChange: function (isHidden) {
                let self = this;
                if (isHidden) {
                    setTimeout(function () {
                        $(self.selector).find('.message').removeClass('show');
                        self.isHidden('false');
                    }, 5000);
                }
            }
        });
    };

});

Make sure to enlarge the timeout 5 secs it to low for customer to actually notice it and maybe click on the message etc.

Hope this will help someone. Also those who are interested please read this. https://alanstorm.com/magento-2-understanding-the-uielement-observe/

0

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.