4

Is it possible to use JavaScript to display a page message? I would like to display one when I receive an ajax response on a custom module I'm working on.

You can see an example of one of these messages after you save your user account info on the frontend.

enter image description here

I know I can build this markup with jQuery and add it to the page, but am wondering if Magento provides a better way of doing this.


I looked at Magento_Theme/js/view/messages and thought maybe I could include it as a dependency of my JavaScript module. Setting the message in the jQuery cookieStorage API which Magento uses to retrieve the message info in Magento_Theme/js/view/messages.

define ([
    'jquery',
    'Magento_Theme/js/view/messages',
    'jquery/jquery-storageapi',
], function ($, messages) {
    'use strict';

    return function () {
        $.cookieStorage.set('mage-messages', [{type: "success", text: "custom message text"}]);
        messages();
    }
}

All though this approach did not work, even though I could see that the message info was retrieved in Magento_Theme/js/view/messages with

this.cookieMessages = _.unique($.cookieStorage.get('mage-messages'), 'text');

It was not displayed on the frontend.

1
8

Super late answer here, but this has bugged me for the longest time and I've finally found the answer. I'm just gonna clear up some stuff about the above two answers.

It really depends on where you want to show your messages. Both of the above suggestions work but it just depends on where you are on the website.

Global Message List

From the sounds of the name, it sounds like exactly what you need. It's not. The name is actually super misleading. This is only used for checkout messages.

You can also use global message list to define a new message container on the checkout to display messages in. This is what payment gateway modules do.

Likelihood is you'll never come into contact with this.

Customer Data

The customer data messages section is for the rest of the website. This is really what you want as you're most likely not on the checkout trying to display messages.

Customer Data (customerData) can get quite messy however. By using customerData.set('messages', messages) you are completely overwriting the messages section with your new message. This can be fine for some people, but if you have crucial messages being displayed then you don't want to be overwriting them.

To completely overwrite the customer data messages object you would do the following:

define(['Magento_Customer/js/customer-data'], function (customerData) {
    customerData.set('messages', {
        messages: [{
            text: 'message to display',
            type: 'success'
        }]
    });
});

Since this overwrites all messages, you may need to append your new message to the end of the existing messages array.

This can be done like this:

define(['Magento_Customer/js/customer-data'], function (customerData) {
    var customerMessages = customerData.get('messages')() || {},
        messages = customerMessages.messages || [];

    messages.push({
        text: 'message to display',
        type: 'success'
    });

    customerMessages.messages = messages;

    customerData.set('messages', customerMessages);
});

By doing this you're not overwriting the current messages. You could also add some duplicate message protection so that you don't end up adding the same message over and over but you don't need to do that really.

The reason for the || {} and || [] is because sometimes there are no messages and will return null. If it returns null then it will use the blank object / array.

6
  • 2
    nice answer, I am currently using Customer Data to show success message but it is disappeared after a few seconds, do you have any solution for that? Dec 13 '19 at 6:53
  • 1
    @SagarParikhSGR This happens because you're inserting the message just before it's wiped. The messages section gets wiped when you load the page. I got around this by creating my own message area in the same template as the already existing ones. This way, nothing from core Magento interferes with showing your messages. If you can't do that for whatever reason, you could always use a setTimeout if needed. Dec 17 '19 at 11:57
  • @DanielGlynnGoodwin Why customer-data-reload just hides messages? If it is so then what is the proper way to prevent this for particular ajax call? Nov 3 '20 at 8:42
  • @ShashankBhatt Because messages are stored in customer data and you're reloading the entirety of customer data. You shouldn't really be reloading customer data anyway. What's your use case? Nov 6 '20 at 11:42
  • HI @DanielGlynnGoodwin I have following code after ajax done which will show messages but due to reload, messages immediately hides as soon as they shows. Can you please suggest what should be proper workaround? $.ajax({ url: someurl, type: "POST", data: form.serialize(), }).done(function (data) { if(data.success == true){ customerData.set('messages', { messages: [{ type: 'success', text: data.message }] }); } return true; }); Nov 7 '20 at 6:54
6

You can use something like following:

    define([
    'mage/url',
    'Magento_Ui/js/model/messageList'
], function (url, globalMessageList) {
    'use strict';
    return {
        /**
         * @param {Object} response
         * @param {Object} messageContainer
         */
        process: function (response, messageContainer) {
            var error;

            messageContainer = messageContainer || globalMessageList;

            if (response.status == 401) { //eslint-disable-line eqeqeq
                window.location.replace(url.build('customer/account/login/'));
            } else {
                var message = response && response.message;

                if (message) {
                    if (message.type === 'error') {
                        messageContainer.addErrorMessage({
                            message: message.text
                        });
                    } else {
                        messageContainer.addSuccessMessage({
                            message: message.text
                        });
                    }
                }
            }
        }
    };
});
3
  • 1
    Thanks that looks good, but for some reason is not working for me
    – Holly
    Aug 10 '18 at 11:54
  • Is there error? you you please add what have you tried? Aug 10 '18 at 12:18
  • its code where should be add? Mar 20 '19 at 7:52
5

I was able to get this working by using Magento_Customer/js/customer-data as a dependency of my JavaScript module. And using the customerData.set() function on it.

define ([
    'jquery',
    'Magento_Customer/js/customer-data',
    'Magento_Ui/js/view/messages',
    'mage/translate'
], function ($, customerData) {
    'use strict';

    return function () {
        var msg = $.mage.__('some message here');

        customerData.set('messages', {
            messages: [{
                type: 'success',
                text: msg
            }]
        });
    }
}
6
  • It works for me, but the notice shows for a while and suddenly gets hidden. Please let me know what I need to do to show notice same as normal magento notices work. Dec 7 '18 at 8:34
  • @DharaBhatti is this happening for you on the checkout, I remember coming across this too. Weirdly it seems to be the default behaviour of Magento, if you copy Magento_Ui/web/template/messages.html to your theme and remove visible: isVisible() from <div data-role="checkout-messages" class="messages" data-bind="visible: isVisible(), click: removeAll"> it should fix it.
    – Holly
    Dec 7 '18 at 14:20
  • @DharaBhatti this probably isn't needed, the message is disappearing because the customer section is being reloaded at which point the messages are cleared. Depending on timing this is likely happening after you added the message.
    – Joel Davey
    Nov 1 '19 at 23:00
  • @Holly Thanks for the reply. I'll try. Nov 14 '19 at 5:04
  • @DharaBhatti did you get a solution for disappeared success message too quickly? I am working on product view page, it is working fine, but message show only for few seconds Dec 13 '19 at 7:09
0

In addition to Daniel Glynn Goodwin or Holly answers, I managed to keep the message displayed on the page by adding a timeout:

  setTimeout(function() {
          customerData.set('messages', {
                  messages: [{
                   type: 'success',
                   text: msg
                  }]
          });
 },1000);

So the final code would be:

     define ([
        'jquery',
        'Magento_Customer/js/customer-data',
        'Magento_Ui/js/view/messages',
        'mage/translate'
    ], function ($, customerData) {
        'use strict';
    
        return function () {
            var msg = $.mage.__('some message here');
    
        setTimeout(function() {
                 customerData.set('messages', {
                      messages: [{
                          type: 'success',
                          text: msg
                      }]
                  });
            },1000);
        });

    
0

After the AJAX request is done, Magento automatically displays the global messages. To display a message on AJAX success/fail, you have to set it in the action instead of the template. Magento's action class, \Magento\Framework\App\Action\Action has an \Magento\Framework\Message\ManagerInterface object named $messageManager for it. All you have to do it set the message in your AJAX handling code. Following is an example

class Save extends \Magento\Framework\App\Action\Action
{

    // some code here...

    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        $location = strtolower($this->_request->getParam('location'));
        $data = [];
        if ($this->verifyValidLocation($location)) {
            $this->session->setCustomerLocation($location);
            $data = [
                'success' => true,
            ];
            //this piece of code sets the success message
            $this->messageManager->addMessage(new \Magento\Framework\Message\Success('Your location information was saved'));
        } else {
            //this piece of code sets the error message
            $this->messageManager->addMessage(new \Magento\Framework\Message\Error('Sorry, we do not deliver to your location.'));
        }
        $result->setData($data);
        return $result;
    }
    
    // rest of the class code here...
}

The reason why the message displayed using daniel's answer (https://magento.stackexchange.com/a/298411/42910) is removed quickly is that right after the AJAX request is completed, Magento makes an AJAX request to /index.php/customer/section/load/?sections=messages&force_new_section_timestamp=true&_=__some_timestamp_here to fetch current messages and then clears all currently displayed messages to displays the fetched messages. Since no message is set in the Action, Magento clears the currently displayed messages and then shows nothing.

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.