magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.56k stars 9.32k forks source link

JQuery custom event 'contentUpdated' isn't always created. #10360

Closed SvanteAvenla closed 7 years ago

SvanteAvenla commented 7 years ago

JQuery custom event 'contentUpdated' isn't always created due to the script adding the event is added before the document is ready.

data-mage-init and text/x-magento-init isn't runned after calling $(.my-class).trigger('contentUpdated') after ajax call.

Preconditions

  1. Magento CE 2.1.7

Steps to reproduce

  1. Load a page
  2. Do an ajax call
  3. Trigger the event contentUpdated with this code -> $('.my-class').trigger('contentUpdated');

Expected result

  1. data-mage-init and text/x-magento-init should be initialized.

Actual result

  1. data-mage-init and text/x-magento-init isn't beeing initialized.

Additional information

This error doesn't always happends, sometimes the event trigger('contentUpdated') work and sometimes it doesn't work. Read my first post to see why this happends.

Information

JQuery custom event 'contentUpdated' isn't always created.

The script creating the event is lib/web/mage/mage.js, and this script is added in the header:

<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_" data-requiremodule="mage/mage" src="http://.../mage/mage.js"></script>

The event is added with this code (row 93):

$('body').on('contentUpdated', function () {
    if (mage) {
        mage.apply();
    }
});

The result is in some cases that the body tag doesn't exist then the event is added, giving the result that the event doesn't exist.

ihor-sviziev commented 7 years ago

@SvanteAvenla it's hard to understand what's happened. Could you describe more detailed what the issue do you have? Please use default issue structure with steps to reproduce, actual result, expected result to make this issue more understandable.

ihor-sviziev commented 7 years ago

I have 2.1.7 and I can't reproduce the issue that you described. Could you add some example that I can run & get this issue?

SvanteAvenla commented 7 years ago

Is hard for me to give more exact instructions on how to reproduct the error. For me it happend when I was using ajax to print a custom made list of related products on the product view. But as I also said, it didn't happend on every page load.

It happends when the code in lib/mage/mage.js (row 93) is executed before the body tag is created. If the body tag doesn't exist, the $('body') return undefined and the event handler for the event 'contentUpdated' is not created.

I ended up fixing it by overriding lib/mage/mage.js in my theme folder and changing the code like this:

$(document).ready(function(event) {
    $('body').on('contentUpdated', function () {
        if (mage) {
            mage.apply();
        }
    });
});

I'm not sure if this is the best way of fixing the issue, that's why I haven't created a pull request. I hope that someone with more in depth knowledge in magento can find the best way to fix this.

ihor-sviziev commented 7 years ago

@SvanteAvenla

It happends when the code in lib/mage/mage.js (row 93) is executed before the body tag is created.

Your custom code shouldn't be loaded in head section. Magento2 use requirejs, so all custom code should be loaded via RequireJS. You can look to JavaScript Developer Guide for more details.

SvanteAvenla commented 7 years ago

My code is not loaded in the header, magentos code is loaded in the header. See my first post. I explain it there. My custom code is using the custom jQuery event 'contentUpdated' created by one of the scripts in the lib folder.

orlangur commented 7 years ago

Are you sure original body tag is not replaced after your AJAX call?

Are you sure this issue is not caused by not triggering contentUpdated after DOM update via AJAX? (like here: https://github.com/magento/magento2/blob/develop/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js#L34)

SvanteAvenla commented 7 years ago

Yes, I'm sure. The ajax call replaced a smaller part of the DOM, not the whole body. I'm sure I triggered the contentUpdated after the ajax respond had been inserted to the DOM. By logging the variables both in my own scripts and in mage.js I know in what order things happend.

Anyway, here is the information if anyone needs it.

magento-engcom-team commented 7 years ago

Closing, as issue seems to be resolved. Please reopen if there are still any problems.

navarr commented 3 years ago

I am currently encountering this error on a project where we're using a custom JavaScript bundler. On a soft-refresh, this works fine; but on a hard-refresh, the .on is called before there is a body in the DOM; leading to future attempts to initialize magento widgets through triggering the contentUpdated on dynamic elements broken.

navarr commented 3 years ago

I solved this little race condition by patching it to listen to the html element.

Cweagans patch here: https://gist.githubusercontent.com/navarr/84bd34c38d449e90a84ffa4e70657276/raw/7c6f3e482ffe37b018b7db44da19e8a8974dd7fd/ROCK-557-handle-contentupdated.patch

If using ECE patching procedures, the paths of the patch will need to be changed from vendor to the webroot lib folder

ihor-sviziev commented 3 years ago

@navarr is there any clear steps to reproduce? If so - could you report a separate issue for that?