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.