Categories


Archives


Recent Posts


Categories


UI Components, `x-magento-init`, and the types Object

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.

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

For backend UI Components, the rendered x-magento-init JSON argument contains two top level keys: types and components

{
    "*": {
        "Magento_Ui/js/core/app": {
            "types": {/*...*/},
            "components": {/*...*/}
        }
    }
}

The Magento_Ui/js/core/app module/application uses the data in components to instantiated a nested tree of uiClass based objets and register them as KnockoutJS view models (accessible via Magento’s customer KnockoutJS scope binding). It was never clear to me what the types information was for. I’ve sort of figured that out – or at least enough that I’m not mystified anymore.

In a components object, I came across the following configuration for a UI Component.

"components": {
    /*...*/
    "cms_page_form": {
        "type": "cms_page_form",
        "name": "cms_page_form",
        "children": {...},
        "dataScope": "data",
        "config": {
            "namespace": "cms_page_form"
        }
    },   
    /*...*/
}        

I would expect to find a component key here that points to the RequireJS module Magento uses as a view model constructor factory (Don’t know what a view model constructor factory is? The Magento 2 UI Components and uiElement Internals series have you covered). There isn’t one – however, there is a type key.

However, if you look up at the types object

"types": {
    /* ... */
    "cms_page_form": {
        "component": "Magento_Ui/js/form/form",
        "provider": "cms_page_form.page_form_data_source",
        "deps": "cms_page_form.page_form_data_source"
    },
    /* ... */
}

You can see there’s a cms_page_form key here that matches the type. This information includes the component key we expected to find. When Magento’s building it’s view models, this types information is merged into each object from components if that object has a type key – this happens here

//File: vendor/magento/module-ui/view/base/web/js/core/renderer/layout.js
define([
    'underscore',
    'jquery',
    'mageUtils',
    'uiRegistry',
    './types'
], function (_, $, utils, registry, types) {
    /*...*/

    node = utils.extend({
    }, types.get(type), defaults, node);    

    /* ...*/
}    

The Magento_Ui/js/core/app/renderer/types registry (./types above, imported as the local variable types) being the registry where this information is stored.

As to why Magento’s core engineers did this – that’s a trickier question. It might be they initially set out to create a new javascript object system independent of their current libraries and ran out of time. It might also be that the components object was too large – and breaking things out into types solved some performance problem. It could also be someone was bored during the eBay wilderness years.

Regardless, knowing that this is a simple alias/merging system should help you when you’re exploring how Magento has implemented a particular feature.

Copyright © Alan Storm 1975 – 2019 All Rights Reserved

Originally Posted: 7th February 2017