junmindereal
8/16/2019 - 7:56 AM

Magento2 - UI Component: Child and Grandchild

Magento2 - UI Components: Child and Grandchild

Child and Grandchild

Block

Note: In this example, we will use:

  • theme = ThemeTest
  • module = Magento_Theme

*In this example I used the default.xml file to add the block where our UI component will appear.

Under app/design/frontend/[vendorname]/[theme]/[module]/layout/default.xml, let us add the block where the UI component template will appear.

<block class="Magento\Framework\View\Element\Template" name="magentotheme_basic_ui" template="Magento_Theme::basic-ui.phtml" />  

Where:

  • class="Magento\Framework\View\Element\Template" is the class name used for templated elemens.
  • template="Magento_Theme::basic-ui.phtml" is the directory where your template is located.
    • ../Magento_Theme/templates/basic-ui.phtml

Template

In ../Magento_Theme/templates/basic-ui.phtml, let us create sample code

<h2>Ui Component 1</h2>
<div class="example" data-bind="scope: 'uiCp'">
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!-- // if no template value in config, you still could declare template directly as below -->
    <!-- //ko template: "Custom_HelloWorld/uiEl-view-model" --><!-- /ko -->
</div>
<script>
/**
 * - Inherit: (uiClass+Ko) > uiElement > uiComponent
 * - Priority Order:JSON.config > JSON > VM.default > VM
 * - inherit from uiElement, you CAN:
 *      - merge config
 *      - use “teamplate” value to fetch html template
 *      - use magent
*       - use binding syntax in html template,such as `<each><if><div translate="" text=""``
 *          - https://devdocs.magento.com/guides/v2.3/ui_comp_guide/concepts/knockout-bindings.html
 *          - https://devdocs.magento.com/guides/v2.3/ui_comp_guide/concepts/magento-bindings.html

 * - inherit from uiComponent, you CAN:
 *      - insrt children
 *      - use displayArea & group
 *      - children & root's ns(namespace) value === root's component name
 *      -`require('uiRegistry').get('uiEl.child1.child2')`
 *
 **/
</script>
<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "uiCp": {
                        "component": "Magento_Theme/js/view/uiEl-view-model",
                        "config": {
                            "template": "Magento_Theme/uiCp-view-model"
                        },
                        "children": {
                            "uiEl1": {
                                "component": "Magento_Theme/js/view/uiEl-view-model",
                                "template": "Magento_Theme/uiEl-view-model",
                                "children": {
                                    "uiEl3": {
                                        "component": "Magento_Theme/js/view/uiEl-view-model",
                                        "template": "Magento_Theme/uiEl-view-model"
                                    }
                                }
                            },
                            "uiEl2": {
                                "component": "Magento_Theme/js/view/uiEl-view-model",
                                "template": "Magento_Theme/uiEl-view-model"
                            }
                        }
                    }
                }
            }
        }
    }
</script>

Where:

  • "scope: 'uiCp'" is the component name under <script type="text/x-magento-init">
  • "component": "Magento_Theme/js/view/uiEl-view-model" is the view model (Javascript file) file
  • "template": "Magento_Theme/uiCp-view-model" is the template (html file) file
  • "template": "Magento_Theme/uiEl-view-model" is the template (html file) file

Create a template in ../Magento_Theme/web/template named uiCp-view-model.html

<table style="border:1px solid red;">
    <tr>
      <th>ns</th>
      <td text="ns"></td>
    </tr>
    <tr>
      <th>index</th>
      <td text="index"></td>
    </tr>
    <tr>
      <th>name</th>
      <td text="name"></td>
    </tr>
    <tr if="elems().length">
      <th>Children</th>
      <td>
        <each args="elems">
          <render />
        </each>
      </td>
  <!--
  same as:
  <//!-- ko foreach: elems --//>
      <//!-- ko template: getTemplate() --//><//!-- /ko --//>
  <//!--/ko--//>

  elems: children components
  -->
    </tr>
  </table>
  use `ko with: getChild('uiEl2')` to get specify child component
  <!-- ko with: getChild('uiEl2') -->
  <render />
  <!-- /ko -->

Create another template in ../Magento_Theme/web/template named uiEl-view-model.html

<table style="border:1px solid red;">
    <tr>
        <th>ns</th>
        <td text="ns"></td>
      </tr>
    <tr>
      <th>index</th>
      <td text="index"></td>
    </tr>
    <tr>
      <th>name</th>
      <td text="name"></td>
    </tr>
    <tr if="elems().length">
      <th>Children</th>
      <td>
        <each args="elems">
          <render />
        </each>
      </td>
    </tr>
  </table>

View Model

Create a uiEl-view-model.js file in ../Magento_Theme/web/js/view

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

    return Component.extend({
        defaults: {
            label: 'Veiw-Model default.label'
        },
        label: 'View-Model label'
    })
});

Note: Define dependencies in define(['uiComponent'], function(...){....});

This is the output of this html code: