Categories


Archives


Recent Posts


Categories


Magento 2: uiElement Name and NS Defaults

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

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.

Copyright © Alan Storm 1975 – 2017 All Rights Reserved

Originally Posted: 29th November 2016