Configuration flow
The following section covers the configuration flow of UI components. Before a UI component is finally displayed on a web page, its configuration undergoes a series of modifications. Starting from the initial reading of the top-level component instance's XML declaration, all the way to the merging of module-specific options.
When the server generates a page response, the configuration of these components in the .xml
declaration files is then modified by the .php
modifiers, and then finally this combined configuration is packed into JSON format and added into the HTTP response body.
On the client-side, this JSON is processed by Magento_Ui/js/core/app
where Magento_Ui/js/core/app
is an alias for the app.js
file. The JSON could be seen in the page source. The Magento_Ui/js/core/app
creates the UI components instances according to the configuration of the JSON using uiLayout
.
The JavaScript application bounds these instances to the corresponding .html
templates, if there are any .html
templates declared in JSON for that particular component. The top-level UI component is bound to the page by the scope
Knockout binding.
Implementation details
This section provides more detailed steps about the configuration flow.
Lets consider an example with the top-level UI component, form
.
Lets imagine we have the following file structure in our module <My_Module>
:
- layout
.xml
file of the Module's page:my_page.xml
- top-level UI Component (form or listing) configuration:
my_form.xml
.php
modifiers that are specific to the module
Keep in mind that the Magento_UI module contains these important files:
- A general, module-agnostic form definition in the
<form>
node of the.xml
definition file:<Magento_Ui_module_dir>/view/base/ui_component/etc/definition.xml
- Default
.xhtml
template for the form, which is referenced indefinition.xml
:<Magento_Ui_module_dir>/view/base/ui_component/templates/form/default.xhtml
- The Form class, which is referenced in
definition.xml
:<Magento_Ui_module_dir>/view/base/web/js/form/form.js
When the request for my_page comes, the server does the following:
- Determines which UI components are used in this particular layout. In the example, the UI components that are used are defined in the
my_form
component's.xml
declaration file. - Searches the
.xml
files with namemy_form
among all modules. The server then merges all themy_form.xml
file(s) into a single configuration object, thus overriding the common properties, so that the latestmy_form.xml
file always has the highest priority. - Merges the resulting configuration (from Step 2 above) with the configuration from the UI module
definition.xml
. The UI moduledefinition.xml
configuration file has the lowest priority, and is overwritten by the merged configuration of allmy_form.xml
files. - Translates the resulting configuration into JSON format and adds it to response body the following way:
Copied to your clipboard<script type="text/x-magento-init">{"*": {"Magento_Ui/js/core/app":{<JSON_configuration>}}}</script>
Now it is the client's turn to process this JSON and generate the UI component's instances. The flow is following:
- RequireJS requires
Magento_Ui/js/core/app
and passes JSON configuration as a parameter. - The
Magento_Ui/js/core/app
callslayout.js
and passes the UI component's configuration into the layout:<Magento_Ui_module_dir>/view/base/web/js/core/renderer/layout.js
. layout.js
creates instances of UI components. That means that each UI component's configuration must have an explicitly declared thecomponent
property in JSON. This property references the.js
file. For example, our form has the component declared in JSON like this:"my_form":{"component":"Magento_Ui/js/form/form"}
. So the instance of this class is created, and properties from the JSON overwrites the properties from the UI component'sdefaults
property. Then resulting properties become the first-level properties of the newly created UI component's instance, and the originaldefaults
property is deleted.- The UI components'
.html
templates (if there are any) are rendered byknockout.js
template engine. This means, that bootstrap.js (required byapp.js
) passes our own template engine for the Knockout. - The
bootstrap.js
binds the component as a Model behind this View (template) using Knockout bindings. The UI components are now displayed on the page, and are fully interactive.