I want to add tabs on the product page, to let admin to add unlimited tabs.

So fields in my grid will be: id, position, tab label, tab content.

Does anyone know how to do this? Maybe any tutorial exist?


Assuming you have the model created for the tab entity already (if not, find a tutorial or use mage2gen.com), this is how to make the tabs appear on the product page.

We make a plugin for Magento\Catalog\Helper\Product\View that looks like this:


namespace Your\Module\Plugin\Magento\Catalog\Helper\Product;

use Your\Module\Model\ResourceModel\Tab\Collection;
use Your\Module\Model\ResourceModel\Tab\CollectionFactory;
use Magento\Framework\View\Result\Page;

class View
    /** @var  Your\Module\Model\ResourceModel\Tab\Collection */
    protected $tabCollection;

    public function __construct(CollectionFactory $collectionFactory)
        $this->tabCollection = $collectionFactory->create();

    public function beforePrepareAndRender(
        \Magento\Catalog\Helper\Product\View $subject, Page $resultPage, ...$args
    ) : array
        $layout = $resultPage->getLayout();

        $detailsBlock = $layout->getBlock('product.info.details');

        // add tabs to the details block
        /** @var Your\Module\Api\Data\TabInterface $tab */
        foreach ($this->tabCollection->addOrder('position', Collection::SORT_ORDER_ASC) as $tab)
            $name = "tab_" . $tab->getTabId();
            $tabBlock = $layout->createBlock(
                ['tab' => $tab, 'data' => ['title' => __($tab->getLabel())]]

        array_unshift($args, $resultPage);

        return $args;

This creates blocks for each tab entity and inserts them into the layout. To make them render as tabs we have to make them children of the product.info.details block and members of the detailed_info group.

We also need to define our custom block type:


namespace Your\Module\Block;

use Your\Module\Api\Data\TabInterface;
use Magento\Framework\View\Element\Template;

class Tab extends Template
    protected $tab;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        TabInterface $tab,
        array $data = []
    ) {
        $this->tab = $tab;

        parent::__construct($context, $data);

    public function toHtml() : string
        return $this->tab->getContent();

This block is assigned a tab and overrides the toHtml method to return the tab's content.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.