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.
First We create a basic module if you don’t know then click here.
<?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Dolphin_CustomProductField', __DIR__);
<?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>
<?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.
<?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(); } }
<?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:
Now We modify the custom fieldset and field into Product From using Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool.
<?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>
<?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; } }
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.
I hope this helps you. For any doubts regarding this topic, please write your doubts in the comments section.