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 foreach
ing 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 displayArea
s
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')
.