How to Add a Custom field at Product Form Magento 2

Written by Mahesh Makwana

Jul 06, 2021

How to Add a Custom field at Product Form Magento 2

We learn how to add a custom field at Product Form in Magento 2. Magento already supports additional product attributes via an inbuilt EAV model. Many developers need to add custom filed/fieldset in product form. And also there are need more modification of our custom fields. This is more demand when you use extra information on the product page which Magento 2 is not provided in default.

Feel free to contack us If you want hire certified Magento developer.

Let’s follow below step to add a custom field to Product Form.

First We create a basic module if you don’t know then click here.

  • Step-1: Create registration.php at app/code/Dolphin/CustomProductField
<?php

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Dolphin_CustomProductField', __DIR__);
  • Step-2: Create module.xml at app/code/Dolphin/CustomProductField/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_CustomProductField" setup_version="1.0.1">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

 

  • Step-3: Now we create custom product attributes. Create InstallData.php at app/code/Dolphin/CustomProductField/Setup
<?php

namespace Dolphin\CustomProductField\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;

    public function __construct(
        EavSetupFactory $eavSetupFactory
    ) {
        $this->eavSetupFactory = $eavSetupFactory;
    }
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        /* Product Custom Title */
        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'custom_title');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'custom_title',
            [
                'type' => 'varchar',
                'label' => 'Custom Title',
                'input' => 'text',
                'required' => false,
                'sort_order' => 10,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'group' => 'custom_content_hide',
                'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
            ]
        );
        /* Product Custom Select Options */
        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'custom_mode');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'custom_mode',
            [
                'type' => 'varchar',
                'label' => 'Custom Select Option',
                'input' => 'select',
                'required' => false,
                'sort_order' => 20,
                'source' => \Dolphin\CustomProductField\Model\Config\Source\CustomModeList::class,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'group' => 'custom_content_hide',
            ]
        );
        /* Product Custom Multi Select Option */
        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'custom_cms_pages');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'custom_cms_pages',
            [
                'type' => 'varchar',
                'label' => 'Custom CMS Pages',
                'input' => 'multiselect',
                'required' => false,
                'sort_order' => 30,Screenshot
                'source' => \Dolphin\CustomProductField\Model\Config\Source\CMSPageList::class,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
                'group' => 'custom_content_hide',
            ]
        );
    }
}

If you need to add to your existing module then you should use UpgradeData. Don’t forget to change your module version before using UpgradeData.

  • Step-4: Create CustomModeList.php at app/code/Dolphin/CustomProductField/Model/Config/Source
<?php

namespace Dolphin\CustomProductField\Model\Config\Source;

use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;

class CustomModeList extends AbstractSource
{

    public function getOptionArray()
    {
        $options = [];
        $options[] = (__('CMS Page HIDE'));
        $options[] = (__('CMS Page SHOW'));
        return $options;
    }

    public function getAllOptions()
    {
        $res = $this->getOptions();
        array_unshift($res, ['value' => '', 'label' => '']);
        return $res;
    }

    public function getOptions()
    {
        $res = [];
        foreach ($this->getOptionArray() as $index => $value) {
            $res[] = ['value' => $index, 'label' => $value];
        }
        return $res;
    }

    public function toOptionArray()
    {
        return $this->getOptions();
    }
}
  • Step-5: Create CMSPageList.php at app/code/Dolphin/CustomProductField/Model/Config/Source
<?php

namespace Dolphin\CustomProductField\Model\Config\Source;

use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;

class CMSPageList extends AbstractSource
{
    protected $_userFactory;
    protected $pageFactory;

    public function __construct(
        \Magento\Cms\Model\PageFactory $pageFactory,
        \Magento\Cms\Api\PageRepositoryInterface $pageRepositoryInterface,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
    ) {
        $this->pageFactory = $pageFactory;
        $this->pageRepositoryInterface = $pageRepositoryInterface;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    }

    public function getOptionArray()
    {
        $searchCriteria = $searchCriteria = $this->searchCriteriaBuilder->create();
        $pages = $this->pageRepositoryInterface->getList($searchCriteria)->getItems();
        $options = [];
        foreach ($pages as $page) {
            $pageData = $this->pageFactory->create();
            $categoryIds = $pageData->load($page->getId());
            $options[$page->getId()] = $page->getTitle();

        }
        return $options;
    }

    public function getAllOptions()
    {
        $res = $this->getOptions();
        array_unshift($res, ['value' => '', 'label' => '']);
        return $res;
    }

    public function getOptions()
    {
        $res = [];
        foreach ($this->getOptionArray() as $index => $value) {
            $res[] = ['value' => $index, 'label' => $value];
        }
        return $res;
    }

    public function toOptionArray()
    {
        return $this->getOptions();
    }
}

After creating and adding above files run magento 2 commands

php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f
php bin/magento cache:clean

You can show custom attributes in product form like Below:

Product Custom Field

 

Now We modify the custom fieldset and field into Product From using Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool.

  • Step-6: Create di.xml at app/code/Dolphin/CustomProductField/etc/adminhtml
<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
        <arguments>
            <argument name="modifiers" xsi:type="array">
                <item name="newFields" xsi:type="array">
                    <item name="class" xsi:type="string">Dolphin\CustomProductField\Ui\DataProvider\Product\Form\Modifier\CustomContent</item>
                    <item name="sortOrder" xsi:type="number">40</item>
                </item>
            </argument>
        </arguments>
    </virtualType>

</config>
  • Step-7: Create CustomContent.php at app/code/Dolphin/CustomProductField/Ui/DataProvider/Product/Form/Modifier
<?php

namespace Dolphin\CustomProductField\Ui\DataProvider\Product\Form\Modifier;

use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Element\MultiSelect;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Fieldset;

class CustomContent extends AbstractModifier
{
    private $locator;
    private $modeList;
    private $pageList;
    private $cacheManager;

    public function __construct(
        \Dolphin\CustomProductField\Model\Config\Source\CustomModeList $modeList,
        \Dolphin\CustomProductField\Model\Config\Source\CMSPageList $pageList,
        LocatorInterface $locator
    ) {
        $this->modeList = $modeList;
        $this->pageList = $pageList;
        $this->locator = $locator;
    }

    public function modifyMeta(array $meta)
    {
        $meta = array_replace_recursive(
            $meta,
            [
                'custom_content' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'label' => __('Custom Content'),
                                'componentType' => Fieldset::NAME,
                                'dataScope' => 'data.product',
                                'collapsible' => true,
                                'sortOrder' => 5,
                            ],
                        ],
                    ],
                    'children' => [
                        'custom_title' => $this->getCustomTitle(),
                        'custom_mode' => $this->getCustomMode(),
                        'custom_cms_pages' => $this->getCustomCmsPages(),
                    ],
                ],
            ]
        );
        /* Hide Custom Content Attributes */
        if (isset($meta['custom-content-hide'])) {
            unset($meta['custom-content-hide']);
        }
        return $meta;
    }

    public function getCustomTitle()
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Custom Title'),
                        'componentType' => Field::NAME,
                        'formElement' => Input::NAME,
                        'dataScope' => 'custom_title',
                        'dataType' => Text::NAME,
                        'sortOrder' => 10,
                    ],
                ],
            ],
        ];
    }

    public function getCustomMode()
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Custom Mode Options'),
                        'component' => 'Dolphin_CustomProductField/js/form/element/custom-mode-list',
                        'componentType' => Field::NAME,
                        'formElement' => Select::NAME,
                        'dataScope' => 'custom_mode',
                        'dataType' => Text::NAME,
                        'sortOrder' => 20,
                        'options' => $this->getCustomModeOptions(),
                    ],
                ],
            ],
        ];
    }

    public function getCustomCmsPages()
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Custom CMS Pages'),
                        'componentType' => Field::NAME,
                        'component' => 'Magento_Catalog/js/components/new-category',
                        'elementTmpl' => 'ui/grid/filters/elements/ui-select',
                        'levelsVisibility' => 1,
                        'disableLabel' => true,
                        'formElement' => MultiSelect::NAME,
                        'dataScope' => 'custom_cms_pages',
                        'chipsEnabled' => true,
                        'dataType' => Text::NAME,
                        'sortOrder' => 30,
                        'required' => 1,
                        'options' => $this->getCustomCmsOptions(),
                        'validation' => ['required-entry' => 1],
                    ],
                ],
            ],
        ];
    }

    public function getCustomModeOptions()
    {
        return $this->modeList->toOptionArray();
    }

    public function getCustomCmsOptions()
    {
        return $this->pageList->toOptionArray();
    }

    public function modifyData(array $data)
    {
        $product = $this->locator->getProduct();
        $productId = (int) $product->getId();
        $cmsPages = [];
        $cmsCategoryIds = '';
        if ($product->getCustomCmsPages()) {
            $cmsPages = array_map('intval', explode(',', $product->getCustomCmsPages()));
        }
        if ($product->getCmsCategoryIds()) {
            $cmsCategoryIds = $product->getCmsCategoryIds();
        }

        $data = array_replace_recursive(
            $data, [
                $productId => [
                    'product' => [
                        'custom_title' => $product->getCustomTitle(),
                        'custom_mode' => $product->getCustomMode(),
                        'custom_cms_pages' => $cmsPages,
                    ],
                ],
            ]);
        return $data;
    }
}
  • Step-8: Create custom-mode-list.js at app/code/Dolphin/CustomProductField/view/adminhtml/web/js/form/element
define([
    'jquery',
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select'
], function ($, _, uiRegistry, select) {
    'use strict';
    return select.extend({
        initialize: function (){
            this._super();
            var customMode = this._super().initialValue;
            setTimeout(function () {
                var customCMSPages = uiRegistry.get('index = custom_cms_pages');
                    if (customMode == 1) {
                        customCMSPages.show();
                    } else{
                        customCMSPages.hide();
                    }

            }, 1000);
            return this;
        },

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            this.fieldDepend(value);
            return this._super();
        },

        /**
         * Update field dependency
         *
         * @param {String} value
         */
        fieldDepend: function (value) {
            setTimeout(function () {
                var customCMSPages = uiRegistry.get('index = custom_cms_pages');
                if (value == 1) {
                    customCMSPages.show();
                } else {
                    customCMSPages.hide();
                }
            }, 500);
            return this;
        }
    });
});

Now please run PHP bin/Magento cache:clean command and refresh product form.

You can see custom fieldset and fields in product form like below.

Custom Fields

You can also modify existing form fieldset and field. In CustomContent.php at Dolphin\CustomProductField\Ui\DataProvider\Product\Form\Modifier file, there are two main methods.

  1. modifyMeta($meta): This method allows you to add and modify fieldset and fields in Product Form. Here the whole product goes into $meta variable, which variable we use for adding and modifying Product Form.
  2. modifyData($data):- This method allows you to save and modifying form Data. In this method, Magento\Catalog\Model\Locator\LocatorInterface class provides your current product data by using $this->locator->getProduct() method which helps you to get and show product data.

I hope this helps you. For any doubts regarding this topic, please write your doubts in the comments section.

Mahesh Makwana

Author

We can help you with

  • Dedicated Team
  • Setup Extended Team
  • Product Development
  • Custom App Development

Schedule a Developer Interview And Get 7 Days Risk-Free Trial

Fill out the form below, and one of our technical experts will reach out to you within 12 hours.

    Google
    |

    4.8

    Google
    |

    4.8

    Google
    |

    4.9

    Google
    |

    4.8

    Google
    |

    4.9

    Copyright © 2024 DOLPHIN WEB SOLUTION. All rights reserved.

    ×

    Hello!

    Click one of our contacts below to chat on WhatsApp

    × How can I help you?
    TO TOP