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.
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
1 2 3 4 5 | <?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Dolphin_CustomProductField', __DIR__); |
- Step-2: Create module.xml at app/code/Dolphin/CustomProductField/etc
1 2 3 4 5 6 7 8 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <?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
1 2 3 | 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:
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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.
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.
- 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.
- 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.