Magento 2 Plugin Implementation for JS Frontend – Step-by-Step Guide

frontendjavascriptmagento2plugin

A plugin as far as I read is created for intercepting a PHP function call and running code before, after, or around that function call. Is there a way how to accomplish that in js file?

How can i intercept Magento 2 module js file function call with another function that is located in another module?

Example: js generates an array and i want to add additional element into that array with another module, before it gets processed by another js function. Similar to what is done in magento checkout customization tutorials but only using js file(s) (adding layout elements dynamically).

PS: Can it be done and if not then why? What might be cons? Sorry if that is against any js patterns or best practices?

Best Answer

You do this with using a requirejs mixin and the mage/utils/wrapper js module.

Heres a demonstration of how the wrapper module functions:

var wrapper = require('mage/utils/wrapper');

function multiply(a, b) {
    return a * b;
}

var wrapped1 = wrapper.wrap(multiply, function (_super) {
    var result = _super();
    return result + 1;
});

var wrapped2 = wrapper.wrap(multiply, function (_super, a, b) {
    a += 1;
    return _super(a, b);
});

multiply(2, 2); // result is 4
wrapped1(2, 2); // result is 5
wrapped2(2, 2); // result is 6

In this example, wrapped1 works like an 'after' plugin, and wrapped2 works like a 'before' plugin. You can combine the two to get an 'around' plugin.

For a real world example, here's how to create a plugin for the collectData method of Magento/Ui/view/base/web/js/form/from.js. We need to use a requirejs 'mixin' to do this.

In your module, create the file Your/Module/view/base/web/requirejs-config.js:

var config = {
    'config': {
        'mixins': {
            'Magento_Ui/js/form/form': {
                'Your_Module/js/plugin': true
            }
        }
    }
};

Now make the file Your/Module/view/base/web/js/plugin.js:

define([
    'mage/utils/wrapper'
], function (wrapper) {
    'use strict';

    return function (Form) {

        var newMethod = wrapper.wrap(Form.collectData, function (_super, items) {
            items = before(items); // the 'before' plugin
            var result = _super(items); // call original method
            return after(result); // the 'after' plugin
        });

        Form.collectData = newMethod; // replace original method with wrapped version

        return Form;
    }
});

You can read more about mixins and wrapper here: http://alanstorm.com/the-curious-case-of-magento-2-mixins/

Related Topic