TUTORIAL: How to implement an admin product tab in Magento 2

14 June 2016

What will you learn in this tutorial?

Basically, you will learn how to implement a product tab in admin product edition page. The tab will be linked to your own model, so the content of such tab will make possible showing/creating/editing data from the custom model.

We will build a kind of “Structured Description” tab, where administrator can add/remove/edit rows which contain a short piece of text (textarea input) and an image.

Then we will display it on fronted, in product page under related products block. As a result, we should see the following result in product page:


Let’s see how to do it – step by step.

Create your custom extension

If you have some experience with Magento 2, you probably know how to create your own extension. Otherwise, you can always pull the extension from SNOW.DOG’s repository.

 You can also install it by composer simply running the following command in your Magento 2 root folder:

Build your setup script

Now it’s time to create a custom table which will store the data manageable under our “Structured Description” product tab.

The table is going to have the following columns: entity_id, product_id, title, description and position

To make it possible we need to create an installer, which basically is Setup/InstallSchema.php and have the table creation code (full code in repo):

Once we have the above done, we can execute in terminal magento setup:upgrade command which will register our extension in Magento and create the previous table in the data base.

Create your own custom model

Here, we will introduce a new Magento 2 functionality called “Service Contracts”. Basically, service contracts are interfaces. However, they are built under some standard to make the code more elegant and logical. You can read more about it on DevDocs provided by Magento.

Now we need to create interfaces Api/CustomDescriptionRepositoryInterface.php and Api/CustomDescriptionInterface.php (full code in repo). They contain some required methods which make the code more stable and reliable. Then, the Model/CustomDescription.php model implements the methods declared in Api/CustomDescriptionInterface.php:

and Model/CustomDescriptionRepository.php will implement the methods declared in Api/CustomDescriptionRepositoryInterface.php:

Once we have defined our interfaces, we need to communicate with Magento to send information about  classes used to implement these methods. That’s why we create a file under etc/di.xml, where we have the following code:

Now, we need to create a model, resource and collection files (check in the repo) which implement our contracts created previously.

It’s important to know, that in the file Model/Resource/CustomDescription.php there is a function which allows to get all structured descriptions for a product using their ID:

Display custom tab in product admin edition page

We display the custom tab under “Advance Settings” tab group. However, we need to create a few files to make it work:

1) view/adminhtml/layout/catalog_product_new.xml:

The previous file inserts the tab under “Advanced Settings” group tab in admin product edition (if you don’t see it, try clearing cache):


When you click it, you’ll see an Ajax request. It won’t work, though. First we need to add the controller linked to the tab URL action (defined in the previous file, under page > body > referenceBlock name=”product_tabs” > block name=”product.custom.description” > arguments > argument name=”url” path=”snowcustomdescription/custom/description) to determine what should be done with the tab.

Create your own controller action

First we need to define the route name for admin actions in the extension, then – create the action which works with our tab. What is to be done:

In etc/adminhtml/routes.xml:

Then the action should be executed in the controller Controller/Admin/Custom/Description.php (check repo for details). This performs the request for tab URL (snowcustomdescription/custom/description).

Create your own blocks and templates for the tab action

First, we need to define a xml file which will link the controller action to a block .php file. So we need: 

a) view/adminhtml/layout/snowcustomdescription_custom_description.xml:

Snowdog\CustomDescription\Block\Adminhtml\Product\Edit\Tab\CustomDescription will link the container of the tab with the block: Block\Adminhtml\Product\Edit\Tab\CustomDescription.php (check our repo for details).

And also we need to create the file of the child of the Block\Adminhtml\Product\Edit\Tab\CustomDescription.php file (defined in the line: $this->addChild(‘custom_description_box’, ‘Snowdog\CustomDescription\Block\Adminhtml\Product\Edit\Tab\CustomDescription\Description’);

However, we still need to create the template files that allow to show content when our custom tab is clicked:

b) view/adminhtml/templates/catalog/product/edit/tab/custom_description.phtml.

This file is the main container for the structured description rows. Also, we need to create the template linked with the block in point c (defined here: protected $_template = ‘Snowdog_CustomDescription::catalog/product/edit/tab/description.phtml’;).

c) view/adminhtml/templates/catalog/product/edit/tab/description.phtml which adds rows to the previous container.

After adding the phtml files, we can now click on our tab (previously, cache should be cleared) and we should see an empty form like this one:


 If we click in “Add New Description” button – nothing happens. First, we need to add some Js code to make it work.

Adding Js files to manage structured description form

Basically, the Js file allows us to make similar operations as standard custom options for product form provides. We can add a structured description, remove or just edit an existing one. It also provides us a sorting functionality in drag & drop tool. In Magento 2, if we want to use a Js file, we need to include it in requirejs (read more about it on Magento’s DevDocs). Again – to make all the Js files work, we need to create the following files:

a) File which contains structured description form operations: view/adminhtml/web/js/custom-description.js (check repo for details). 

b) Require js file: view/adminhtml/web/require-config.js:

Once we include Js files, and clean cache, we can play with the structured descriptions form: adding and removing rows.


However, there is still no way to save the descriptions. We need to build an observer which will save the data from the form in the tables. 

Build your own plug-in to save structured description

We are almost done in the admin part. This point can be done by observers. But, as Magento 2 has new feature that allows to listen any method by dependency injection, we will create such functionality for our extension. Now, we are talking about plugins (more info in official Magento 2 documents). Basically, to build a plugin we need:

a) Configure the plug-in by the file: etc/adminhtml/di.xml (Note: this piece of code was updated at 17/08/2016 due to editor conflicts format):

As we can see under type node we write the class which we want to listen (in our case, we want to save structured description once saving the product action in admin is finished). In plugin node we have a name, to add unique plug-in name, and type, which determines what class contains the plugin functionality.

 b) And the plugin file itself: Plugin/Adminhtml/ProductSave.php (full code in repo): Here is the function which saves/updates the structured description in our table:

If we look at the file into vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php there is an execute() method which is the function that triggers saving product action. So, we want to listen such method once it is finished. That’s why the name of our plugin method is called afterExecute(). The prefix after is the one which makes possible to listen a method after its execution is finished. Once the plugin is correctly set, we can save our structured description data.


Show structured description in product page

Once we finish with the admin part, we have to work on the frontend. We include the frontend descriptions in content aside in product page. We need to create a layout, template and block files for it:

 a) Layout file: view/frontend/layout/catalog_product_view.xml:

b) Template file: view/frontend/templates/catalog/product/view/custom-description.phtml:






                                    getData(‘image’); ?>” title=”getData(‘title’); ?>” alt=”getData(‘title’); ?>”/>

</td>                             <td>

                                    getData(‘description’); ?>

</td>                         </tr>                     <?php endforeach; ?>                 </tbody>             </table>         </div>     </div> <?php endif;?>

c) Block file: Block/Catalog/Product/View/CustomDescription.php (full code in repo). It extends from Magento\Catalog\Block\Product\View\AbstractView. This allows to get a current product ID. What’s important is that the function makes getting structured description for the current product possible:

As you can see we are using our customDescriptionRepository which implements getCustomDescriptionByProductId method from our Api/CustomDescriptionRepositoryInterface.php. That means it is using service contracts successfully. 

If everything went as it should, we get the frontent look just like on the screen showed on the beginning of this tutorial.

Short summary

This tutorial was made not only to help in including a tab in product admin page. It might aslo be helpful in other basic Magento 2 issues such as: building models, plugins, controllers, etc. 

Thank you for reading.

If anything is not understandable or needs more clarification – let us know in comments and we will try to help.

Update (13-10-2017)

The code has been updated and now it’s compatible with Magento 2.1.x and 2.2.x versions. You can update the extension by composer or download the newer code in the official repository: https://github.com/SnowdogApps/module-product-custom-description