How to add custom javascript in Magento 2 with requireJS

Magento 2 brings some new features in javascript. One of them is “requireJS” (javascript file loader) and second is “jQuery“, a very popular js library. One of the biggest benefits is using requireJS which means that Magento 2 is ready for the upcoming HTTP2 protocol. In the next few steps we will explain how to create valid javascript code for use in requireJS. Let’s start with an example.
As usual, we need to create a valid Magento 2 module like seen on the screen shoot below:
You may notice some differences between Magento 1 and Magento 2 in the fact that all javascript, layout and template phtml files now belong to the module. Also, our javascript files are in our module located on the directory path: “app/code/Inchoo/Js/view/frontend/web/js/“. For this example we created two js files: “inchoo.js” and “logger.js”
Take a look at our javascript code which is valid for using in requireJS environment.
define([
"jquery",
"logger",
"jquery/ui"
], function($, logger) {
"use strict";
logger.log('inchoo.js is loaded!!');
logger.log(logger);
//creating jquery widget
$.widget('inchoo.js', {
_create: function() {
//options which you can pass from js.phtml file in json format
logger.log(this.options);
//access to element p#test
logger.log(this.element);
//for exmple, you can create some click event or something else
this.element.on('click', function(e){
logger.log("You click on element: " + e.target);
});
}
});
return $.inchoo.js;
});
You will notice that the javascript code on the top uses “define” function.
This function is from requireJs – first parameter of “define” function is array of dependency and second parameter is definition of our function.
Definition function should always return an object. In our example our function returns “$.inchoo.js”.
You can read more about define function on url: http://requirejs.org/docs/api.html#define
In our example, our javascript uses jQuery, jQueryUI and logger. All dependency should be declared in “define” function. You can see that we put as the first argument next array:
["jquery", "logger", "jquery/ui"]
In definition of our function we created jquery widget and we put all logic in widget constructor “_create“. JQuery and logger are passed as next parameters: “$” and “logger”.
Source code of our logger class is below. You can notice that our class doesn’t need any dependency and that in “define” function there’s only definition function which returns object as we mentioned before.
define(function() {
"use strict";
return {
log : function(param){
console.log(param);
}
};
});
All files should be declared in “requirejs-config.js” file – this is config file which uses requireJs.
var config = {
map: {
'*': {
inchoojs: 'Inchoo_Js/js/inchoo',
logger: 'Inchoo_Js/js/logger'
}
}
};
Next step will be to explain how to load and use our javascript. In order to use/load our javascript, you have to add the next code in some phtml file. Our complete example of js.phtml file is below:
<script type="text/x-magento-init">// <![CDATA[ { "#test": { "Inchoo_Js/js/inchoo": {"url":"http://www.example.url", "method":"post"} } } // ]]></script>
In Magento 2 there is a javascript parser (located in script “lib/web/mage/apply/scripts.js”) which reads script tags with attribute type=”text/x-magento-init” and load/process them with “child” json data in curly brakets:
"#test": {
"Inchoo_Js/js/inchoo":
{"url":"http://www.example.url", "method":"post"}
}
You will notice “#test“, this is id of html element which is passed to jquery widget and it is available in our script, over property “this.element“. Other elements “url” and “method” are options which are also passed from json object to our widget and these options are available in the script over js property “this.options“. These options can be defined as you want.
If you did everything as above, javascript should work and you should have a script tag in html head like in a screen shot below 🙂 .
If this or anything else regarding Magento development confuses you, we will gladly check out your site and offer technical insights on what to improve based on our detailed custom report. Feel free to get in touch!
15 comments
Thanks, Please let us know how to access this outside create function
Hi,
I have purchased a small javascript based design editor which I would like to load when a given theme page is visited. I kep reading various posts but I can’t seem to get the js files or the css files to load on the module’s page.
Can anyone please help me with some advice on how to approach this problem. This design editor also features some css design and is basically a standalone webpage.
Thanks
I truing to load my main.js on home and cart page only , currenlty it is loading on all pages , can any one knows how to load on specify pages in custom module .
var config = {
deps: [
"NameSpace_ReviewRating/js/main",
],
map: {
'*': {
'slickjs': 'NameSpace_ReviewRating/js/slick/slick',
'sliderjs': 'NameSpace_ReviewRating/js/slick/tiny-slider'
}
},
shim: {
"slickjs": ["jquery"],
"sliderjs": ["jquery"]
}
};
"#test": {
"Inchoo_Js/js/inchoo":
{"url":"http://www.example.url", "method":"post"}
}
can be shorted to:?
"#test": {
"inchoojs":
{"url":"http://www.example.url", "method":"post"}
}
I want to include paypal plus external js in magento2, it already contains jquery library which conflicts with magento jquery. How do i load it ?
This is the js which i load as external
https://www.paypalobjects.com/webstatic/ppplusdcc/ppplusdcc.min.js
Error Uncaught TypeError: $.widget is not a function
What I have to input in Inchoo/Js/view/frontend/layout/default.xml?
How are you loading the js.phtml? What little magic piece am I missing? YES, what goes in the default.xml? Obviously not a block because you didn’t include any block classes. Doesn’t requirejs-config.js have to go in /frontend and not frontend/web to get it to actually load?
I have a question about prototype.js. Is it there in magento 2?
hmm. It`s strange because I have problem with .phtml step
//
still getting errors about :
Uncaught SyntaxError: Unexpected token /
two slashes before CDATA are causing this error.
Any ideas why ?
How did you solve it?
Did you solve this issue? I have the same problem.
Got this solved by removing comments.
I had something like this
“componentName”: {} //comment
taking the co
“componentName”: {}
comments off fixed it like this:*
Thanks for this info, would think that a lot of people would help this.