0

I'm trying to update quantities in the shopping cart in Magento 2.3.2 via an ajax request but I'm confused about the error messages.

In my code after the ajax request has completed I execute the following js code which I'd like to present any error messages that will be created by Magento e.g. the request qty is not available.

define([
  'jquery',
  'Magento_Checkout/js/action/get-totals',
  'Magento_Customer/js/customer-data',
  'underscore',
  'Magento_Theme/js/view/messages',
  'loader',
  'Ioweb_Cart/node_modules/jquery-form/dist/jquery.form.min',
  'domReady!',
], function ($, getTotalsAction, customerData, _, messageModel) {

...
...

var cookieMessages = $.cookieStorage.get('mage-messages');
        if (!_.isEmpty(cookieMessages)) {
          customerData.set('messages', {messages: cookieMessages});
          $.cookieStorage.set('mage-messages', '');
        }

The code works fine for the most part, but unfortunately the error message shown will disappear really really fast.

enter image description here

I've read the various threads about modifying the function

        onHiddenChange: function (isHidden) {
            var self = this;

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

In file Magento_Ui::js/view/messages.js

However this will change the timings only when the page is actually loaded not in my particular example.

I've also tried reloading the sections but to no avail.

            var messages_section = ['messages'];
            //customerData.invalidate(messages_sections);
            customerData.reload(messages_section);

So how do I make the message last longer or what is the proper way to force the messages component to refetch the messages from the storage and redraw itself?

What's even stranger, is that if I refresh the page without my code, the message stays there forever so it doesn't even go away after 5 seconds like the function suggests.

I've added a debugger breakpoint in all functions of all messages.js files in Magento_Ui and Magento_Theme, and during the procedure of displaying / hiding the message no breakpoint is hit

2
  • Did you redeploy your static content after making changes? Commented Jul 14, 2022 at 0:45
  • I'm in developer mode and I cleared all static files of course.
    – gabtzi
    Commented Jul 14, 2022 at 5:57

1 Answer 1

0

I'm answering my own question as I read in different posts a lot of people are struggling with this to no avail.

In file vendor/magento/module-customer/view/frontend/web/js/customer-data.js:

There is an event listener for ajax requests which will activate on all ajax requests every time they complete.

     * Events listener
     */
    $(document).on('ajaxComplete', function (event, xhr, settings) {
        var sections,
            redirects;

        if (settings.type.match(/post|put|delete/i)) {
            sections = sectionConfig.getAffectedSections(settings.url);

            if (sections) {
                customerData.invalidate(sections);
                redirects = ['redirect', 'backUrl'];

                if (_.isObject(xhr.responseJSON) && !_.isEmpty(_.pick(xhr.responseJSON, redirects))) { //eslint-disable-line
                    return;
                }
                customerData.reload(sections, true);
            }
        }
    });

So the flow goes like this

  1. User does an action in the website
  2. An ajax form is submitted
  3. The code is processing the response
  4. A message is added in the messages model
  5. The message is rendered in the messages component.
  6. The ajaxComplete event is fired
  7. All the sections are refreshed with the now empty messages queue.
  8. The message that was once visible disappears.

The workaround in my case was to render my messages on a different event instead of during the response processing.

  $(document).on('ajaxStop', function (event, xhr, settings){
    var cookieMessages = $.cookieStorage.get('mage-messages');
    if (!_.isEmpty(cookieMessages)) {
      customerData.set('messages', {messages: cookieMessages});
      $.cookieStorage.set('mage-messages', '');
    }
  })

Since ajaxStop is fired after ajaxComplete, this will make messages stick until the next ajaxRequest is completed.

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.