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.

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 – 2017 All Rights Reserved

Originally Posted: 28th October 2016