Continuing in our informal series of quickies explaining the more magical defaults
properties of Magento uiElement
objects, today we’ll explore the modules
default.
The modules
default allows you to link a property in your new object with an object in Magento’s uiRegistry
via the registry’s “async” feature.
If that didn’t make sense, consider the following program. You can run this from your browser’s javascript console on the admin’s customer listing page (Customers -> All Customers
)
//normally we'd pull in RequireJS module via `define`
reg = requirejs('uiRegistry');
UiElement = requirejs('uiElement');
//make sure the registry has a key of customer_listing.customer_listing
//if not, you're not on the All Customers page or Magento's changed
//something since this was written
console.log ( reg.get('customer_listing.customer_listing') );
//create our new class/constructor-function with a
//modules default set
OurConstructorFunction = UiElement.extend({
defaults:{
modules:{
foo:'customer_listing.customer_listing'
}
}
});
//instantiate a new object
object = new OurConstructorFunction;
//call the now defined "foo" method to fetch the
//customer_listing.customer_listing registry entry
console.log( object.foo() );
//test that its the same object
console.log( object.foo() === reg.get('customer_listing.customer_listing'));
As you can see from the above program, the
defaults:{
modules:{
foo:'customer_listing.customer_listing'
}
}
configuration automatically gave our instantiated objects a foo
method which returns the customer_listing.customer_listing
object from the registry.
The async Method
All these “registry getter” methods are setup via the uiRegistry
object’s async
method.
console.log(object.foo);
function async(name, registry, method) {
var args = _.toArray(arguments).slice(3);
if (_.isString(method)) {
//...
You can see the entire method definition here
//File: vendor/magento/module-ui/view/base/web/js/lib/registry/registry.js
//the method definition
async: function (query) {
return async.bind(null, query, this);
},
//the async function that's bound with `bind` in the method definition
function async(name, registry, method) {
var args = _.toArray(arguments).slice(3);
if (_.isString(method)) {
registry.get(name, function (component) {
component[method].apply(component, args);
});
} else if (_.isFunction(method)) {
registry.get(name, method);
} else if (!args.length) {
return registry.get(name);
}
}
The uiElement
source binds the foo
property in the code below, where name
is foo
(or whatever property you use in your modules
default).
#File: vendor/magento/module-ui/view/base/web/js/lib/core/element/element.js
requestModule: function (name) {
var requested = this._requesetd;
if (!requested[name]) {
requested[name] = registry.async(name);
}
return requested[name];
}
The async
method lets you setup a callback that fetches a registry object – even before that registry object is set. Consider the following program
//normally we'd pull in RequireJS module via `define`
reg = requirejs('uiRegistry');
UiElement = requirejs('uiElement');
//create our new class/constructor-function with a
//modules default set for the ourUniqueRegistryName
//registry key
OurConstructorFunction = UiElement.extend({
defaults:{
modules:{
bar:'ourUniqueRegistryName'
}
}
});
//instantiate a new object
object = new OurConstructorFunction;
//use the bar method/callback now and it returns nothing
console.log( object.bar() );
//however, set something in the registry with
//the ourUniqueRegistryName key from the modules default
reg.set('ourUniqueRegistryName', 'something');
//and now you can fetch the item
console.log( object.bar() );
If you follow along with the comments above, you can see how this async()
function enables us to link in a registry object even if that object isn’t yet registered.
The new modules
default method also behaves differently depending on the arguments you pass it. For example, dovetailing off our last code sample
//define a simple object/method
var test = {
hello:function(noun){
console.log("Hello " + noun);
}
}
//re-register the ourUniqueRegistryName registry key
reg.set('ourUniqueRegistryName', test);
//fetch the entire object by using no arguments
console.log( object.bar() );
//call the `hello` method by passing in the
//string "hello" as the first argument, and
//then the following arguments will be passed
//on to the hello call
object.bar('hello', "World");
This method calling seems like a bit of a bind
parlor trick, as the following also works
object.bar().hello("World")
but as Magento occasionally uses the former syntax in its core systems code, you’ll want to be familiar with it.