Adding JavaScript in Magento 2

There are currently three ways of adding JavaScript in Magento 2 using RequireJS, which are presented by the three JS module types: plain module, jQuery widget and UIComponent.

Each type will require you to have set up a basic Magento module structure, including a requirejs-config.js file. For example, let’s assume that a custom.js file is to be included.

// app/code/Vendor/Module/view/frontend/requirejs-config.js

var config = {
    map: {
        '*': {
            custom: '<Vendor>_<Module>/js/custom'
        }
    }
};

Plain Module

To add JavaScript via a plain module, you can define your JS file like the following:

// app/code/Vendor/Module/view/frontend/web/js/custom.js

define([
    "jquery"
], function($, custom) {
    "use strict";

    return function (config, element) {
        $(element).click(function (event) {
            alert('Hey, the element was clicked!');
        });

    };
});

The code consists of two major parts. The define statement, which declares all dependencies and the return statement. Because of the way in which Magento 2 executes the JavaScript, the return statement takes two parameters: element and config.

jQuery Widget

The jQuery widget has the same define statement as a plain module, but the return part is slightly different. It uses config and element parameters, but now they are hidden inside of its structure.

// app/code/Vendor/Module/view/frontend/web/js/custom.js

define([
    "jquery"
], function($, custom) {
    "use strict";

    // Create the widget
    $.widget('custom.js', {
        _create: function() {

            // Access to the config
            var config = this.config;

            // Access to the JS element
            var element = this.element;

            element.on('click', function(e){
                alert('Hey, the element was clicked!');
            });
        }

    });

    return $.custom.js;
});

Using the JavaScript

So what is element and this.element? This is where you need to load and use the JavaScript in a .phtml file.

You can use the data-mage-init attribute.

// somefile.phtml

<div class="some-class" data-mage-init='{ "custom": {...} }'></div>

Notice within this attribute resides a JSON object that lists the custom module and config for the module.

You could also use the text/x-magento-init attribute. This approach allows the execution of a JS module without connecting it to a specific DOM-node or multiple nodes.

// somefile.phtml

<script type="text/x-magento-init">
{
    // Components initialised on the element defined by selector
    "<element_selector>": {
        "<js_component1>": ...,
	"<js_component2>": ...
    },

    // Components initialised without binding to an element
    "*": {
        "<js_component3>": ...
    }
}
</script>

Extend UIComponent JS

You can extend an existing UIComponent’s JavaScript in Magento 2 by tweaking your requirejs-config.js and adding a require.js mixin.

// app/code/Vendor/Module/view/frontend/requirejs-config.js

var config = {
    'config': {
        'mixins': {
            'Magento_Ui/js/form/form': {
                '<Vendor>_<Module>/js/custom': true
            }
        }
    }
};

Then within your custom.js file:

// app/code/Vendor/Module/view/base/web/custom.js

define([
], function () {
    'use strict';

    return function (Form) {
        return Form.extend({
            initialize: function () {
                this._super();
                alert('Successfully extended the UIComponent!');
            }
        });
    }
});

Note: This article is based on Magento CE version 2.1.