Why JS Breaks with RequireJS in Magento 2 Templates and How to Fix

javascriptrequirejs

I am using a custom theme called Porto for Magento 2.

I have found an issue where when I load the page with dev tools enabled and having disable cache checked, a number of js errors pop up.

Most of the errors are one of:

Uncaught TypeError: $(...).swMegamenu is not a function
Uncaught TypeError: $(...).owlCarousel is not a function
Uncaught TypeError: Cannot read property 'timepicker' of undefined

The reason is that the libraries these function calls depend on are not loaded yet, but why is that surely requirejs would have ensured the function is only run once the js libraries have been downloaded.

Looking at one of the errors is:

<script type="text/javascript">
    require([
        'jquery',
        'Smartwave_Megamenu/js/sw_megamenu'
    ], function ($) {
        $(".sw-megamenu").swMegamenu();
    });
</script>

With template hints we track the code to: app/design/frontend/Smartwave/porto/Smartwave_Megamenu/templates/topmenu.phtml

So Smartwave_Megamenu/js/sw_megamenu is not loaded. When the function is called.

How can I fix this issue? As you have to reload the page once all the assets have been downloaded for the megamenu and owlslider etc. to actually work.

Update: The library is definitely loaded as when I:

console.log(require.defined("Smartwave_Megamenu/js/sw_megamenu"));

It returns true

After some more investigation it turns out that function is not defined in jquery at that point:

if(!$.isFunction($.fn.swMegamenu)) will fail

As in swMegaMenu.js extending jquery has not happened at that point:

$.fn.swMegamenu = function() {
        $(".navigation.sw-megamenu li.classic .submenu, .navigation.sw-megamenu li.staticwidth .submenu, .navigation.sw-megamenu li.classic .subchildmenu .subchildmenu").each(function(){
            $(this).css("left","-9999px");
            $(this).css("right","auto");
        });

Best Answer

Finally this is a solutions that works for me.

https://themeforest.net/item/porto-ultimate-responsive-magento-theme/9725864/comments?page=293#comment_16606311

"Kroellie

Finally figured out the solution for javascript messages:

Uncaught TypeError: $(...).swMegamenu is not a function
Uncaught TypeError: $(...).stellar is not a function
Uncaught TypeError: $(...).owlCarousel is not a function
Uncaught TypeError: $.widget is not a function

If you suffer the same, do this:

create a requirejs-config.js in the root of the child theme

app/design/frontend/Smartwave/porto_child and put in the following:
 var config = {
    shim: {
        jquery: {
            exports: '$'
        },
        'Smartwave_Megamenu/js/sw_megamenu':
            {
                deps: ['jquery']
            }, 
        'owl.carousel/owl.carousel.min':
            {
                deps: ['jquery']
            },
        'js/jquery.stellar.min': 
            {
            deps: ['jquery']
            },
        'js/jquery.parallax.min':
            {
            deps: ['jquery']
            }
    }
};

And change the entries:

    <script src="jquery.js" />
    <script src="bootstrap/js/bootstrap.min.js" />
    <script src="fancybox/js/jquery.fancybox.js" />

To:

    <remove src="jquery.js" />
    <remove src="bootstrap/js/bootstrap.min.js" />
    <remove src="fancybox/js/jquery.fancybox.js" />

Within file:

app/design/frontend/Smartwave/porto_child/Magento_Theme/layout/default_head_blocks.xml

Tada! No more need for merging javascripts, no more javascript errors! I have no need for the fancybox, turned it off, but if you do require it, I guess it should be included in the requirejs as well. "

Related Topic