Add Custom Textarea Field to Product Form in Magento 2 Admin

adminhtmlmagento2moduleproduct

I want to add a custom product attribute to the product form in the admin area.

https://devdocs.magento.com/guides/v2.2/howdoi/customize-form-configuration.html and https://devdocs.magento.com/guides/v2.1/ui_comp_guide/concepts/ui_comp_xmldeclaration_concept.html, but I do not get it yet.

As far as I understand the documentation, all that's necessary is a new app/code/Mycompany/Catalog/view/adminhtml/ui_component/product_form.xml file. Mine looks like this:

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="mycompany">
        <field name="my_field_name">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="label" xsi:type="string">My Field Name</item>
                    <item name="visible" xsi:type="boolean">true</item>
                    <item name="dataScope" xsi:type="string">product[my_field_name]</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="formElement" xsi:type="string">textarea</item>
                    <item name="sortOrder" xsi:type="number">15</item>
                    <item name="source" xsi:type="string">product</item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

My field appears, but does not store data when I submit the form via the "save" button. How can I make it store data?

Edit: This is my setup script:

/**
 * Adds my_field_name attribute if it does not exists already.
 *
 * {@inheritdoc}
 *
 * @codingStandardsIgnoreStart
 */
public function addMyFieldNameAttribute(ModuleDataSetupInterface $setup)
{
    //codingStandardsIgnoreEnd
    /**
     * @var \Magento\Catalog\Setup\CategorySetup
     */
    $catalogSetup = $this->categorySetupFactory->create(['setup' => $setup]);
    $catalogSetup->addAttribute(
        \Magento\Catalog\Model\Product::ENTITY,
        'my_field_name',
        [
            'group' => 'General',
            'type' => 'text',
            'label' => 'My Field Name',
            'input' => 'textarea',
            'class' => '',
            'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class,
            'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
            'visible' => true,
            'required' => false,
            'user_defined' => 1,
            'default' => '',
            'apply_to' => '',
            'visible_on_front' => false,
            'is_html_allowed_on_front' => true,
            'used_in_product_listing' => true,
            'is_used_in_grid' => false,
            'is_visible_in_grid' => false,
            'is_filterable_in_grid' => false,
        ]
    );
}

Best Answer

Create app/code/Anshu/Custom/Setup/InstallData.php setup file in your module as follows:

<?php

declare(strict_types=1);

namespace Anshu\Custom\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Catalog\Api\Data\ProductAttributeInterface;
use Magento\Eav\Model\Config as EavConfig;

class InstallData implements InstallDataInterface
{
    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * @var EavConfig
     */
    private $eavConfig;

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

        // adding eav attribute to product
        $attributeCode = 'custom_attribute';

        $entityType = ProductAttributeInterface::ENTITY_TYPE_CODE;
        $setId = $eavSetup->getDefaultAttributeSetId($entityType); 
        $groupId = $eavSetup->getDefaultAttributeGroupId($entityType, $setId);

        // to get the group name
        $groupName = $eavSetup->getGroupName($entityType, $setId, $groupId, 'attribute_group_name'); 

        $eavSetup->addAttribute($entityType, $attributeCode, [
            'label' => 'My Custom Attribute',
            'input' => 'textarea',
            'is_wysiwyg_enabled' => 1,
            'required' => 0,
            'user_defined' => 1,
            'visible_on_front' => 1,
            'group' => $groupName,
            'sort_order' => 30,
        ]);
    }
}

It seems that the following line is causing the issue in your code:

$catalogSetup = $this->categorySetupFactory->create(['setup' => $setup]);

And make sure if the attribute that you have created is there in the database.
And as far as I remember, there is no need to add any code in the ui-form component, if you have added the product attribute correctly, then it will appear automatically in the admin form.