How to pass dynamic variables to a component in Magento 2

How to pass dynamic variables to a component in Magento 2
()

Sometimes there is a scenario when we need to control the components display, customize the front-end texts or customize the element classes, and all controlled from admin section. We can call this feeding front-end from back-end.

So today we will explore the possibilities to achieve such scenario.

Begin with creating a new module

Know/Module/etc/module.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Know_Module" setup_version="1.0.0" />
</config>

Create registration.php: strong>Know/Module/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Know_Module',
    __DIR__
);

We will use our custom page to display the component output. So go ahead and create a routes.xml file first and define a custom route.

Know/Module/etc/frontend/routes.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="module" frontName="module">
            <module name="Know_Module"/>
        </route>
    </router>
</config>

Now create Index controller

Know/Module/Controller/Index/Index.php

<?php
namespace Know\Module\Controller\Index;

/**
 * Module Index
 */
class Index implements \Magento\Framework\App\ActionInterface
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param \Magento\Framework\View\Result\PageFactory $pageFactory
     */
    public function __construct(\Magento\Framework\View\Result\PageFactory $pageFactory)
    {
        $this->resultPageFactory = $pageFactory;
    }

    /**
     * @inheritDoc
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set(__('KnowTheMage Module'));
        return $resultPage;
    }
}

Next we need to create the layout module_index_index.xml file and specify the template.

Know/Module/view/frontend/layout/module_index_index.xml

<?xml version="1.0"?>

<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="km.component"
                   template="Know_Module::component.phtml" />
        </referenceContainer>
    </body>
</page>

Now create the component.phtml template file: Know/Module/view/frontend/templates/component.phtml

<?php
/**
 * @var \Magento\Framework\View\Element\Template $block
 */
?>

<div id="km-component" data-bind="scope: 'km-component-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>
<script type="text/x-magento-init">
    {
        "#km-component": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "km-component-scope": {
                        "component": "Know_Module/js/view/km-component",
                        "config": {
                            "template": "Know_Module/km-template"
                        }
                    }
                }
            }
        }
    }
</script>

Inside the template we have specified the component and template. So next we need to create the component first. Go ahead and create km-component.js.

Know/Module/view/frontend/web/js/view/km-component.js

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

    return Component.extend({
        defaults: {
            title: 'KM Template',
            content: 'Lorem ipsum is a placeholder text.',
            btnText: 'Click',
            isPrimary: true
        }
    });
});

Inside component we have created some default properties with predefined values. We will make use of these properties inside the template. Go ahead and create the km-template template file.

Know/Module/view/frontend/web/template/km-template.html

<h2 data-bind="text: title"></h2>
<p data-bind="html: content"></p>
<div data-bind="css: {
    'primary': isPrimary,
    'secondary': !isPrimary
}">
    <button data-bind="attr: {
        type: 'button',
        title: btnText
    }, class: 'action',
    css: {
        'primary': isPrimary,
        'secondary': !isPrimary
    }"><span data-bind="text: btnText"></span></button>
</div>

Run setup upgrade command to install module.

php bin/magento setup:upgrade

The output should look similar to the screenshot below:

Know the mage output

Now it is time to pass some dynamic data to component and render inside html template. Edit the component.phtml template file and specify the variable values under config node.

Know/Module/view/frontend/templates/component.phtml

<?php
/**
 * @var \Magento\Framework\View\Element\Template $block
 */
?>

<div id="km-component" data-bind="scope: 'km-component-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>
<script type="text/x-magento-init">
    {
        "#km-component": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "km-component-scope": {
                        "component": "Know_Module/js/view/km-component",
                        "config": {
                            "template": "Know_Module/km-template",
                            "title": "A Custom title",
                            "content": "This is custom content passed from phtml file.",
                            "btnText": "Secondary button",
                            "isPrimary": false
                        }
                    }
                }
            }
        }
    }
</script>

Flush the cache and reload the page. The changes should reflected now:

Passing variable to component

Our next step is to give power to admin to control over the content display. For this purpose we need steps below:

  1. Create a simple configuration.
  2. Retrieve data from configured options.
  3. Push dynamic data to the component.
  4. First go ahead and create a system.xml file under etc/adminhtml directories.

    Know/Module/etc/adminhtml/system.xml

    <?xml version="1.0"?>
    
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
        <system>
            <tab id="kmconfig" translate="label" sortOrder="190">
                <label>Know the Mage</label>
            </tab>
            <section id="knowthemage" translate="label" type="text" sortOrder="70" showInDefault="1"
                     showInWebsite="1" showInStore="1">
                <class>separator-top</class>
                <label>Component Settings</label>
                <tab>kmconfig</tab>
                <resource>Know_Module::configuration</resource>
                <group id="general" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1"
                       showInStore="1">
                    <label>General options</label>
                    <field id="title" translate="label comment" type="text" sortOrder="0" showInDefault="1" showInWebsite="1"
                           showInStore="1">
                        <label>Title</label>
                        <comment>Specify the component title.</comment>
                    </field>
                    <field id="content" translate="label" type="textarea" sortOrder="10" showInDefault="1" showInWebsite="1"
                           showInStore="1">
                        <label>Content</label>
                    </field>
                    <field id="btn_txt" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1"
                           showInStore="1">
                        <label>Button text</label>
                    </field>
                    <field id="is_primary_btn" translate="label" type="select" sortOrder="25" showInDefault="1" showInWebsite="1"
                           showInStore="1">
                        <label>Primary button</label>
                        <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                    </field>
                </group>
            </section>
        </system>
    </config>
    
    

    According to configuration we have specified a custom resource. So next create acl.xml under etc directory.

    Know/Module/etc/acl.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
        <acl>
            <resources>
                <resource id="Magento_Backend::admin">
                    <resource id="Magento_Backend::stores">
                        <resource id="Magento_Backend::stores_settings">
                            <resource id="Magento_Config::config">
                                <resource id="Know_Module::configuration" title="KnowtheMage Component" translate="title"
                                          sortOrder="60" />
                            </resource>
                        </resource>
                    </resource>
                </resource>
            </resources>
        </acl>
    </config>
    
    

    Flush the cache and the admin configuration page looks like the screenshot below:

    Admin Configuration Page

    Edit the layout module_index_index.xml file and replace the class attribute.

    Know/Module/view/frontend/layout/module_index_index.xml

    <?xml version="1.0"?>
    
    <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="Know\Module\Block\KMComponent" name="km.component"
                       template="Know_Module::component.phtml" />
            </referenceContainer>
        </body>
    </page>
    
    

    Now create specified KMComponent block class and add getConfigArray method inside it.

    Know/Module/Block/KMComponent.php

    <?php
    namespace Know\Module\Block;
    
    use Magento\Framework\View\Element\Template;
    use Magento\Store\Model\ScopeInterface;
    
    class KMComponent extends Template
    {
        /**
         * Returns the list of configuration
         *
         * @return array
         */
        public function getConfigArray(): array
        {
            return [
                'title' =>  $this->_scopeConfig->getValue('knowthemage/general/title', ScopeInterface::SCOPE_STORE),
                'content' =>  $this->_scopeConfig->getValue('knowthemage/general/content', ScopeInterface::SCOPE_STORE),
                'btn_txt' =>  $this->_scopeConfig->getValue('knowthemage/general/btn_txt', ScopeInterface::SCOPE_STORE),
                'is_primary_btn' =>  (int)$this->_scopeConfig->getValue('knowthemage/general/is_primary_btn', ScopeInterface::SCOPE_STORE),
            ];
        }
    }
    
    

    Next open the component.phtml template file and specify the dynamic values under config key.

    Know/Module/view/frontend/templates/component.phtml

    <?php
    /**
     * @var \Know\Module\Block\KMComponent $block
     */
    
    $config = $block->getConfigArray();
    ?>
    
    <div id="km-component" data-bind="scope: 'km-component-scope'">
        <!-- ko template: getTemplate() --><!-- /ko -->
    </div>
    <script type="text/x-magento-init">
        {
            "#km-component": {
                "Magento_Ui/js/core/app": {
                    "components": {
                        "km-component-scope": {
                            "component": "Know_Module/js/view/km-component",
                            "config": {
                                "template": "Know_Module/km-template",
                                "title": "<?= /* @noEscape */ $config['title'] ?>",
                                "content": "<?= /* @noEscape */ $config['content'] ?>",
                                "btnText": "<?= /* @noEscape */ $config['btn_txt'] ?>",
                                "isPrimary": <?= /* @noEscape */ $config['is_primary_btn'] ?>
                            }
                        }
                    }
                }
            }
        }
    </script>
    
    

    Now open the admin configuration and specify the content.

    Admin setting values

    Flush the cache and reload the module page. The changes will be similar to the screenshot below:

    Dynamic content output

    We have successfully passed the dynamic values to our component. If we make any changes from admin, those will be reflected accordingly.

    How useful was this post?

    Click on a star to rate it!

    Average rating / 5. Vote count:

    No votes so far! Be the first to rate this post.

    As you found this post useful...

    Follow us on social media!

    We are sorry that this post was not useful for you!

    Let us improve this post!

    Tell us how we can improve this post?

2 Comments

  • Content is very good and it help me to improving my knowladge.
    thanks

    • I’m really pleased that you found the content so beneficial.

Leave a Reply

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