The name
and ns
defaults
#File: vendor/magento/module-ui/view/base/web/js/lib/core/element/element.js
defaults: {
/* ... */
name: '',
ns: '${ $.name.split(".")[0] }',
/* ... */
}
are another pair of defaults that don’t make a lot of sense in the context of a traditional programming object system. Like the provider
default, the name
default is most often set by the Magento_Ui/js/core/renderer/layout
module from server side rendered JSON.
#File: vendor/magento/module-ui/view/base/web/js/core/renderer/layout.js
function initComponent(node, Constr) {
var component = new Constr(_.omit(node, 'children'));
registry.set(node.name, component);
}
For the full details of how this works you’ll need to work your way through the UI Component series.
As for the purpose of the name element – it’s to uniquely identify a component in the uiRegistry
. You can also see where Magento actually registers a component in the initComponent
function above
#File: vendor/magento/module-ui/view/base/web/js/core/renderer/layout.js
registry.set(node.name, component);
Because a component’s name uniquely identifies it in the uiRegistry
, there’s many features of the uiElement
system that end up treating the name as though it were a unique identifier. For example, in the recently discussed localStorage abstraction’s configuration we learned that Magento uses the object’s name
to build a namespace in the browser’s localStorage store.
#File: vendor/magento/module-ui/view/base/web/js/lib/core/element/element.js
storageConfig: {
provider: 'localStorage',
namespace: '${ $.name }',
path: '${ $.storageConfig.provider }:${ $.storageConfig.namespace }'
},
The NS Defaults
The ns
defaults (short for namespace) uses an ES6 template literal to pluck the first portion of a component’s name
ns: '${ $.name.split(".")[0] }',
So, if your component’s server side rendered name is customer_listing.customer_listing.foo.baz
, then the ns
will be customer_listing
. The ns
defaults was introduced in the 2.1.x branch, and appears to be the result of a few different RequireJS modules needing to search the tree of UI Components from the top level node.
While name
and ns
are pretty straight forward properties to understand, here’s why they “don’t make a lot of sense in the context of a traditional programming object system”. Consider the following program
//normally you'd grab `uiElement` via `define` dependencies
UiElement = requirejs('uiElement');
//create a new constructor function for our own object type
OurConstructorFunction = UiElement.extend({
defaults:{
name:'our_rad_object'
}
});
//instantiate two objects
o1 = new OurConstructorFunction;
o2 = new OurConstructorFunction;
//two different objects
console.log(o1 === o2);
//have the same name
console.log(o1.name === o2.name);
This is a pretty “Programming 101” thing – all we’re doing is instantiating a couple of objects from a constructor function (think “class” instead of constructor function if you’re coming from another language). However, because the name
isn’t unique, uiElement
object features that rely on the name
being unique won’t work correctly. It’s also the sort of “won’t work correctly” that includes silent failures and data integrity problems.
The problem here seems to be an early design decision (or lack thereof) that bound uiElement
objects too tightly with with the uiRegistry
. At this point it’s probably too late (for Magento) to untie these systems, so we’ll just need to solider on. Just keep this in mind if you’re trying to use uiElement
objects as a rational programming system.