Magento 2 provides much information about the product on the Product details page. Tabs are more useful when a product has multiple types of descriptions and information. We can add a custom tab on the product details page. If you need to add dynamic custom tabs on the product details page then follow the below steps to achieve this.
Create registration.php at app/code/Dolphin/DynamicCustomTabs
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Dolphin_DynamicCustomTabs', __DIR__ );
Create module.xml at app/code/Dolphin/DynamicCustomTabs/etc
<?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="Dolphin_DynamicCustomTabs" setup_version="1.0.0"> <sequence> <module name="Magento_Catalog"/> <module name="Magento_Backend"/> </sequence> </module> </config>
Create events.xml at app/code/Dolphin/DynamicCustomTabs/etc
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="layout_generate_blocks_after"> <observer name="dyanmic_tabs_add" instance="Dolphin\DynamicCustomTabs\Observer\DynamicTabs" /> </event> </config>
Here event is only generated during the initial page render on a non-cache page. At that time we add dynamic child blocks for the custom tab.
Create DynamicTabs.php at app/code/Dolphin/DynamicCustomTabs/Observer
<?php namespace Dolphin\DynamicCustomTabs\Observer; use Dolphin\DynamicCustomTabs\Model\TabConfig; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; class DynamicTabs implements ObserverInterface { const PARENT_BlOCK_NAME = 'product.info.details'; const RENDERING_TEMPLATE = 'Dolphin_DynamicCustomTabs::dynamic_tab_renderer.phtml'; private $tabs; public function __construct(TabConfig $tabs) { $this->tabs = $tabs; } public function execute(Observer $observer) { $layout = $observer->getLayout(); $blocks = $layout->getAllBlocks(); foreach ($blocks as $key => $block) { if ($block->getNameInLayout() == self::PARENT_BlOCK_NAME) { foreach ($this->tabs->getTabs() as $key => $tab) { $block->addChild( $key, \Magento\Catalog\Block\Product\View::class, [ 'template' => self::RENDERING_TEMPLATE, 'title' => $tab['title'], 'jsLayout' => [ $tab ] ] ); } } } } }
Here we add custom tabs array to page layout child block in product.info.details container block.
Create dynamic_tab_renderer.phtml at app/code/Dolphin/DynamicCustomTabs/view/frontend/templates
<?php if (!empty($block->getJsLayout())) { $jsLayout = \Zend_Json::decode($block->getJsLayout()); foreach ($jsLayout as $layout) { if (isset($layout['type']) && 'template' === $layout['type'] && isset($layout['data'])){ echo $this->getLayout()->createBlock($layout['data']['type']) ->setDisplayType($layout['data']['name']) ->setTemplate($layout['data']['template'])->toHtml(); } else { ?> <h1><?= $layout['title']; ?></h1> <div><?= $layout['description']; ?></div> <?php } } }
Create di.xml at app/code/Dolphin/DynamicCustomTabs/etc/frontend
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Catalog\Block\Product\View\Details"> <plugin name="add_tab_product_view_page_description" type="Dolphin\DynamicCustomTabs\Plugin\Description" /> </type> </config>
Create Description.php at app/code/Dolphin/DynamicCustomTabs/Plugin
<?php namespace Dolphin\DynamicCustomTabs\Plugin; use Dolphin\DynamicCustomTabs\Model\TabConfig; class Description { private $tabs; public function __construct( TabConfig $tabs ) { $this->tabs = $tabs; } public function afterGetGroupSortedChildNames( \Magento\Catalog\Block\Product\View\Details $subject, $result ) { if (!empty($this->tabs->getTabs())) { foreach ($this->tabs->getTabs() as $key => $tab) { $sortOrder = isset($tab['sortOrder']) ? $tab['sortOrder'] : 45; $result = array_merge($result, [ $sortOrder => 'product.info.details.' . $key]); } } return $result; } }
Create TabConfig.php at app/code/Dolphin/DynamicCustomTabs/Model
<?php namespace Dolphin\DynamicCustomTabs\Model; class TabConfig { private $tabs = [ 'tabA' => [ 'title' => 'Dyanmic Tab A', 'description' => 'Dynamic Tab A Description', 'sortOrder' => 50 ], 'tabB' => [ 'title' => 'Dynamic Tab B', 'description' => 'Dynamic Tab B Description', 'sortOrder' => 60 ], 'tabC' => [ 'title' => 'Dynamic Tab C', 'description' => 'Dynamic Tab C Description', 'sortOrder' => 70 ], ]; public function getTabs() { return $this->tabs; } }
Here we define an array of dynamic tabs. we can add phtml file in custom tabs using the below array structure:
'tabD' => [ 'title' => 'Dynamic phtml Tab', 'type' => 'template', 'data' => [ "type" => "Magento\Framework\View\Element\Template", "name" => "dynamic.phtml.custom.tab", "template" => "Dolphin_DynamicCustomTabs::TemplateFileName.phtml" ], 'description' => '', 'sortOrder' => 80 ]
We can also add a widget to dynamically in custom tabs using below array structure:
'tabE' => [ 'title' => 'Recently Viewed', 'type' => 'template', 'data' => [ "type" => "Magento\Reports\Block\Product\Widget\Viewed", "name" => "custom.recently.view.products", "template" => "Magento_Reports::widget/viewed/content/viewed_list.phtml" ], 'description' => '', 'sortOrder' => 90 ],
you can also create a UI form to store the above data and maintain dynamic tabs using database entry. you need to follow the above array structure to store and retrieve data for dynamic custom tabs.
I hope this helps you. For any doubts regarding this topic, please write your doubts in the comments section.