6

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?

Anna Völkl
17.4k6 gold badges61 silver badges142 bronze badges
asked Dec 26, 2016 at 2:10

1 Answer 1

13

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/

answered Feb 4, 2017 at 2:12
3
  • Doesn't seem to work for me. The only way I can get the mixin to intercept the original method is using Form.extend({... otherwise it simply ignores everything else using the logic provided above. Commented Feb 13, 2018 at 23:48
  • You're correct, since Form is a uiClass constructor, we should extend it. The above method should be used for modules that export an object. Commented Feb 14, 2018 at 3:26
  • We can use wrapper.wrapSuper to extend a js object, refer: devdocs.magento.com/guides/v2.3/javascript-dev-guide/javascript/… Commented Jan 15, 2020 at 7:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.