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:
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:
Our next step is to give power to admin to control over the content display. For this purpose we need steps below:
- Create a simple configuration.
- Retrieve data from configured options.
- Push dynamic data to the component.
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:
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.
Flush the cache and reload the module page. The changes will be similar to the screenshot below:
We have successfully passed the dynamic values to our component. If we make any changes from admin, those will be reflected accordingly.











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.