0

I need to add the below field into the product form. Click Here

enter image description here InstallData.php

<?php

namespace Vendorename\ModuleName\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]);
        /* Root category ids */
        //$eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'cms_category_ids');
        // $eavSetup->addAttribute(
        //     \Magento\Catalog\Model\Product::ENTITY,
        //     'cms_category_ids',
        //     [
        //         'type' => 'varchar',
        //         'label' => 'CMS Categories',
        //         'input' => 'select',
        //         'required' => false,
        //         'sort_order' => 90,
        //         'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
        //         'group' => 'Related Content',
        //     ]
        // );

        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'related_title');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'related_title',
            [
                'type' => 'varchar',
                'label' => 'Title',
                'input' => 'text',
                'required' => false,
                'sort_order' => 10,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'group' => 'Related Content',
            ]
        );

        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'related_mode');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'related_mode',
            [
                'type' => 'varchar',
                'label' => 'Mode',
                'input' => 'select',
                'required' => false,
                'sort_order' => 20,
                'component' => 'Vendorename_ModuleName/js/form/element/related-mode-list',
                'source' => \Vendorename\ModuleName\Model\Config\Source\RelatedModeList::class,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'group' => 'Related Content',
            ]
        );

        $eavSetup->removeAttribute(\Magento\Catalog\Model\Product::ENTITY, 'related_cms_pages');
        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'related_cms_pages',
            [
                'type' => 'varchar',
                'label' => 'CMS Pages',
                'input' => 'multiselect',
                'required' => false,
                'sort_order' => 30,
                'levelsVisibility' => 1,
                'disableLabel' => true,
                'chipsEnabled' => true,
                'component' => 'Magento_Catalog/js/components/new-category',
                'elementTmpl' => 'ui/grid/filters/elements/ui-select',
                'source' => \Vendorename\ModuleName\Model\Config\Source\CMSPageList::class,
                'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                'group' => 'Related Content',
            ]
        );
    }
}

Here related_mode is a dependent field which hide and show on related_cms_pages field. And Form Data not also save and not see in edit mode.

Please Help me.

10
  • Your magento version? Jun 25, 2021 at 5:20
  • I am using Magento 2.4.2.
    – Msquare
    Jun 25, 2021 at 5:22
  • @RohanHapani Have you any idea about it? Please help me to achieve.
    – Msquare
    Jun 25, 2021 at 7:21
  • have you tried magento way of creating product attribute from backend? store->attributes(product)->add new attribute
    – Asad Ullah
    Jun 25, 2021 at 7:43
  • But I am creating a module. so attributes are also created when module.
    – Msquare
    Jun 25, 2021 at 8:23

1 Answer 1

2

Please Follow Below Steps.

Step-1: Create registration.php at app/code/VendoreName/ModuleName

<?php
 
use Magento\Framework\Component\ComponentRegistrar;
 
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'VendoreName_ModuleName', __DIR__);

Step-2: Create module.xml at app/code/VendoreName/ModuleName/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="VendoreName_ModuleName" 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/VendoreName/ModuleName/Setup

<?php
 
namespace VendoreName\ModuleName\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' => \VendoreName\ModuleName\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,
                'source' => \VendoreName\ModuleName\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/VendoreName/ModuleName/Model/Config/Source

<?php
 
namespace VendoreName\ModuleName\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/VendoreName/ModuleName/Model/Config/Source

<?php
 
namespace VendoreName\ModuleName\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 the above files run Magento 2 commands

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

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/VendoreName/ModuleName/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">VendoreName\ModuleName\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/VendoreName/ModuleName/Ui/DataProvider/Product/Form/Modifier

<?php
 
namespace VendoreName\ModuleName\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(
        \VendoreName\ModuleName\Model\Config\Source\CustomModeList $modeList,
        \VendoreName\ModuleName\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' => 'VendoreName_ModuleName/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/VendoreName/ModuleName/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 the PHP bin/Magento cache:clean command and refresh the product form. You can see custom fieldset and fields in product form.

You can also modify the existing form fieldset and field. In CustomContent.php at VendoreName\ModuleName\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.

enter image description here

I Hope This Helps You.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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