0

I found an easy hello world example from Max Pronko which uses text/x-magento-init to define a uiComponent.

MODULE/view/frontend/templates/script.phtml

<div data-bind="scope: 'pronko-component'">
    <h2 data-bind="text: title"></h2>
</div>

<script type="text/x-magento-init">
   {
       "*": {
           "Magento_Ui/js/core/app": {
               "components": {
                   "pronko-component": {
                       "component": "Pronko_UiComponent/js/component",
                       "title": "Hello World!"
                   }
               }
           }
       }
   }
</script>

MODULE/view/frontend/layout/default.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="pronko.uicomponent"
                   template="Pronko_UiComponent::script.phtml" />
        </referenceContainer>
    </body>
</page>

MODULE/view/frontend/web/js/component.js

define([
    'uiElement'
], function(Component) {
    'use strict';

    return Component.extend();
});

This shows "Hello world" in the frontend.


How can I rewrite this, to use XML uiComponent instead?

I tried it like this:

Company/Shipping/view/frontend/templates/test.phtml

<div data-bind="scope: 'foobar'">
    <h2 data-bind="text: title"></h2>
</div>

Company/Shipping/view/frontend/web/js/test.js

define([
    'uiElement'
], function(Component) {
    'use strict';

    return Component.extend();
});

Company/Shipping/view/frontend/layout/default.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="company.shipping.test" template="Company_Shipping::test.phtml">
                <arguments>
                    <argument name="jsLayout" xsi:type="array">
                        <item name="components" xsi:type="array">
                            <item name="foobar" xsi:type="array">
                                <item name="component" xsi:type="string">Company_Shipping/js/test</item>
                                <item name="title" xsi:type="string">Hello world!</item>
                            </item>
                        </item>
                    </argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

But it does not write any data into the <h2> where it should put the title data "Hello world!" into it.

I've read the official documentation but the topic is a chaos with no practical examples.

3

Because you still need to use x-magento-init ;)

Check vendor/magento/module-checkout/view/frontend/templates/cart/shipping.phtml:

<div id="block-summary"
     data-bind="scope:'block-summary'"
     class="content"
     data-role="content"
     aria-labelledby="block-shipping-heading"
>
    <!-- ko template: getTemplate() --><!-- /ko -->
    <script type="text/x-magento-init">
    {
        "#block-summary": {
            "Magento_Ui/js/core/app": <?= /* @noEscape */ $block->getJsLayout() ?>
        }
    }
    </script>

This is how you initialize uiComponents. In XML you only declare components and their configuration. Someone can ask "Why do it this using XML? Perhaps it is better to put everything in .phtml?" The reason is the configuration can get quite complex plus you can easily extend/modify configuration using xml.

I recommend to read: https://devdocs.magento.com/guides/v2.4/ui_comp_guide/concepts/ui_comp_config_flow_concept.html

So in general in your case you do something like:

<div id="foobar" data-bind="scope: 'foobar'">
    <h2 data-bind="text: title"></h2>
</div>

<script type="text/x-magento-init">
    {
        "#foobar": {
            "Magento_Ui/js/core/app": <?= /* @noEscape */ $block->getJsLayout() ?>
        }
    }
</script>
2
  • 1
    Nice thank you! I hope it would be described in the documentation but it is always a unstructured mess and misses so much information... It is quite confusing too, because I also saw many .html templates in view/frontend/web ... which do not use text/x-magento-init and still work. – Black Oct 22 '20 at 20:34
  • 1
    I understand. Imagine how difficult it was when there was almost no documentation in the beginning of Magento 2. Anyway Magento 2 frontend architecture is quite complex. I also recommend Mage2.tv courses by Vinai Kopp or Swiftotter (JS/Frontend guides). Not free but worth if you want to learn. – JanuszJanczy Oct 22 '20 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.