Categories


Archives


Recent Posts


Categories


Magento 2: Understanding UI Component Regions

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!

I thought I’d finished up with UI Components, but then I started investigating the checkout application and stumbled across regions.

In the aforementioned UI Components series, we learned that a “UI Component” is a nested tree of RequireJS modules and KnockoutJS templates which a programmer can use as an HTML node’s KnockoutJS view model via a custom data-binding named scope.

However, it looks like there’s another organizing method for UI Components. When you call insertChild on auiCollection/Magento_Ui/js/lib/core/class object, Magento will check the child object you’re inserting for a displayArea property. If it finds this property, Magento will update an internal regions property on the uiCollection object. You can see this on the checkout page with a little console javascript

reg = requirejs('uiRegistry');
reg.get('checkout').regions    
Object {}
    authentication: function...
    estimation: function...
    messages: function...
    progressBar: function...
    sidebar: function...
    steps: function...

You can see the individual components inside a region via the getRegion method

reg = requirejs('uiRegistry')
reg.get('checkout').getRegion('steps')()

This returns an array of instantiated view model objects. So when you call the following via a KnockoutJS template

#File: vendor/magento/module-checkout/view/frontend/web/template/onepage.html
<!-- ko foreach: getRegion('steps') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->           

Knockout is foreaching over the same array returned by a call to requirejs('uiRegistry').get('checkout').getRegion('steps')().

The aforementioned displayArea property that organizes items into these region buckets comes from the x-magento-init JSON object. When the Magento_Ui/js/core/renderer/layout module (covered briefly in UI Component Data Sources) reads through and parses this JSON data, it ends up calling insertChild on the uiCollection objects.

The Magento_Ui/js/core/renderer/layout module is still a bit of a mystery to me, but it seems like only direct children of a uiCollection model can have a displayArea/region (as a uiCollection object is the only object with a getRegion or insertChild method).

This also seems like something that’s more of a thing in the front end UI Component/Knockout Scopes like the checkout, but the backend braintree UI Component XML seems to use displayAreas

vendor/magento/module-braintree/view/adminhtml/ui_component/braintree_report.xml
44: <item name="displayArea" xsi:type="string">dataGridActions</item
58: <item name="displayArea" xsi:type="string">dataGridActions</item
66: <item name="displayArea" xsi:type="string">dataGridFilters</item

and there’s some mentions of displayArea in the stock component definitions.

vendor/magento/module-ui/view/base/ui_component/etc/definition.xml
25: <item name="displayArea" xsi:type="string">bottom</item>
38: <item name="displayArea" xsi:type="string">dataGridFilters</item>
54: <item name="displayArea" xsi:type="string">dataGridFilters</item>
90: <item name="displayArea" xsi:type="string">bottom</item>
406: <item name="displayArea" xsi:type="string">dataGridActions</item>
419: <item name="displayArea" xsi:type="string">dataGridActions</item>

So this is definitely a universal UI Component feature.

This looks like a useful feature – but this second shadow hierarchy does create some confusing situations. For example, the onepage.html template has the following

#File: vendor/magento/module-checkout/view/frontend/web/template/onepage.html
<!-- ko foreach: getRegion('messages') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->

However, there’s no direct child of the checkout uiComponent named messages. There is, however, a checkout.errors child with a displayArea of messages

console.log(reg.get('checkout.errors').displayArea);
messages

This is the view Magento’s fetching with getRegion('messages').

Copyright © Alan Storm 1975 – 2019 All Rights Reserved

Originally Posted: 28th October 2016