Read More
Read More
Menu Close

    How to Intialize Js Component Using Layout XML in Magento2

    How to use Initialize Js Component on custom phtml file using layout xml in Magento2

    In Magento2 mainly we have seen on checkout page all Js components loads using xml, these components are defined in checkout_index_index.xml file.

    We can also define our custom Js Components using our xml Layout File.

    1. Let’s create our required xml file: customjs_index_index.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomJs
     * @author    Webkul
     * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    -->
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <update handle="customer_account"/>
        <body>
            <referenceContainer name="content">
                <block class="Webkul\CustomJs\Block\CustomJs" name="customjs_test" template="Webkul_CustomJs::account/customjs.phtml" cacheable="false">
                </block>
            </referenceContainer>
        </body>
    </page>

    2. Create Block file Webkul\CustomJs\Block\CustomJs.php

    <?php
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomJs
     * @author    Webkul
     * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    namespace Webkul\CustomJs\Block;
    
    class CustomJs extends \Magento\Framework\View\Element\Template
    {
        /**
         * @var array
         */
        protected $jsLayout;
    
        /**
         * @param \Magento\Framework\View\Element\Template\Context $context
         * @param array $data
         */
        public function __construct(
            \Magento\Framework\View\Element\Template\Context $context,
            array $data = []
        ) {
            parent::__construct($context, $data);
            $this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : [];
        }
    
        /**
         * @return string
         */
        public function getJsLayout()
        {
            return \Zend_Json::encode($this->jsLayout);
        }
    }
    

    3. Now we need to create our phtml file customjs.phtml

    Searching for an experienced
    Magento 2 Company ?
    Read More
    <div id="customjs-component" data-bind="scope:'custom-js-field'">
        <!-- ko template: getTemplate() --><!-- /ko -->
        <script type="text/x-magento-init">
        {
            "#customjs-component": {
                "Magento_Ui/js/core/app":  <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
            }
        }
        </script>
    </div>

    Ok, now takes a closer look on above code.
    we have initialized our custom compenent and load the js components by getJsLayout() Method.

    You can see we have defined this Method in our Block File, which is providing Js layouts.
    But we haven’t defined jsLayout in our customjs_index_index.xml file yet.

    Let’s open it again and update with this code.

    <?xml version="1.0"?>
    <!--
    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomJs
     * @author    Webkul
     * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    -->
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <update handle="customer_account"/>
        <body>
            <referenceContainer name="content">
                <block class="Webkul\CustomJs\Block\CustomJs" name="customjs_test" template="Webkul_CustomJs::account/customjs.phtml" cacheable="false">
                    <arguments>
                        <argument name="jsLayout" xsi:type="array">
                            <item name="components" xsi:type="array">
                                <item name="custom-js-field" xsi:type="array">
                                    <item name="component" xsi:type="string">uiComponent</item>
                                    <item name="config" xsi:type="array">
                                        <item name="template" xsi:type="string">Webkul_CustomJs/js-group</item>
                                    </item>
                                    <item name="children" xsi:type="array">
                                        <item name="my-child-js" xsi:type="array">
                                            <item name="sortOrder" xsi:type="string">1</item>
                                            <item name="component" xsi:type="string">Webkul_CustomJs/js/view/my-child-js</item>
                                            <item name="displayArea" xsi:type="string">my-child-js</item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </argument>
                    </arguments>
                </block>
            </referenceContainer>
        </body>
    </page>

    Now what we really did here,
    We have defined the jsLayout as arguments, so we can get all these arguments in our Block File as

    $this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : [];

    You will see that all the components with its children nodes are assigned to “Magento_Ui/js/core/app.js” component.

    We have called a function getTemplate() in our phtml file

    When this method is called Magento checks for the template defined in custom-js-field scope which we have defined as attribute in our phtml file

    <div id="customjs-component" data-bind="scope:'custom-js-field'">

    We have also defined children components in our customjs_index_index.xml file, let learn how we can use them as well.

    Let create Html template file Webkul\CustomJs\view\frontent\web\template\js-group.html which we have defined.

    <item name="components" xsi:type="array">
        <item name="custom-js-field" xsi:type="array">
            <item name="component" xsi:type="string">uiComponent</item>
            <item name="config" xsi:type="array">
                <item name="template" xsi:type="string">Webkul_CustomJs/js-group</item>
            </item>

    Open this file and update with this code.

    <!-- 
    	/**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomJs
     * @author    Webkul
     * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
     -->
     
    <!-- ko foreach: getRegion('my-child-js') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
    <!--/ko-->

    When this template load it will look for the area with name my-child-js in customjs_index_index.xml file.

    we already defined it in our xml file.

    <item name="children" xsi:type="array">
        <item name="my-child-js" xsi:type="array">
            <item name="sortOrder" xsi:type="string">1</item>
            <item name="component" xsi:type="string">Webkul_CustomJs/js/view/my-child-js</item>
            <item name="displayArea" xsi:type="string">my-child-js</item>
        </item>
    </item>

    Children items can also contains define component, we can define nested children as many as we want.

    Now we need to create Webkul_CustomJs/js/view/my-child-js.js file

    /**
     * Webkul Software.
     *
     * @category  Webkul
     * @package   Webkul_CustomJs
     * @author    Webkul
     * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com)
     * @license   https://store.webkul.com/license.html
     */
    /*jshint browser:true jquery:true*/
    /*global alert*/
    define([
        'jquery',
        'uiComponent',
        'ko',
    ], function ($, Component, ko) {
            'use strict';
    
            return Component.extend({
                defaults: {
                    template: 'Webkul_CustomJs/view/my-child-js'
                },
                selectedChoice: ko.observable(),
                initialize: function () {
                    this._super();
                },
            });
        });

    We can call html template from our js components also by passing template key with value on defaults object.
    Or we can call same html template file from xml for example:

    <item name="config" xsi:type="array">
        <item name="template" xsi:type="string">Webkul_CustomJs/js-group</item>
     </item>

    That’s it!

    . . .
    Discuss on Helpdesk

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    1 comments

  • Sasikiran Kesavan
    Hi Team,

    Thank you for the brief info about layout component. Can you please provide the above module as zip file. so i could explore more regarding this.

  • Back to Top