Magento – Magento 2:Custom Field Value in Edit Products Section

adminformmagento2product-edit

I have added a custom tab in admin Products Edit section

http://i.prntscr.com/b78b12c41b3546ba8bd9d657dabcef98.png

The values in the select field are values from my custom tables. I have saved corresponding id of the label and product id to my custom table. I have used the following method for this.

Created a file app/code/Vendor/Module/etc/adminhtml/di.xml

<?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">
        <arguments>
            <argument name="modifiers" xsi:type="array">
                <item name="custom-fieldset" xsi:type="array">
                    <item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\CustomFieldset</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                </item>
            </argument>
        </arguments>
    </virtualType>
</config>

created file app/code/Vendor/Module/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php

<?php
namespace Vendor\Module\Ui\DataProvider\Product\Form\Modifier;

use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Framework\UrlInterface;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\Form\Fieldset;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\MultiSelect;
use Magento\Ui\Component\Form\Field;

class CustomFieldset extends AbstractModifier
{

    // Components indexes
    const CUSTOM_FIELDSET_INDEX = 'custom_fieldset';
    const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
    const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // Fields names
    const FIELD_NAME_TEXT = 'example_text_field';
    const FIELD_NAME_SELECT = 'example_select_field';
    const FIELD_NAME_MULTISELECT = 'example_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    protected $locator;

    /**
     * @var ArrayManager
     */
    protected $arrayManager;

    /**
     * @var UrlInterface
     */
    protected $urlBuilder;

    /**
     * @var array
     */
    protected $meta = [];

    protected $productlabelModel;

    /**
     * @param LocatorInterface $locator
     * @param ArrayManager $arrayManager
     * @param UrlInterface $urlBuilder
     */
    public function __construct(
        LocatorInterface $locator,
        ArrayManager $arrayManager,
        \Vendor\Module\Model\ResourceModel\Productlabel\CollectionFactory $productlabelModel,
        UrlInterface $urlBuilder
    ) {
        $this->locator = $locator;
        $this->arrayManager = $arrayManager;
        $this->productlabelModel = $productlabelModel;   
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * Data modifier, does nothing in our example.
     *
     * @param array $data
     * @return array
     */
    public function modifyData(array $data)
    {
        return $data;
    }

    /**
     * Meta-data modifier: adds ours fieldset
     *
     * @param array $meta
     * @return array
     */
    public function modifyMeta(array $meta)
    {
        $this->meta = $meta;
        $this->addCustomFieldset();

        return $this->meta;
    }

    /**
     * Merge existing meta-data with our meta-data (do not overwrite it!)
     *
     * @return void
     */
    protected function addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $this->meta,
            [
                static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * Declare ours fieldset config
     *
     * @return array
     */
    protected function getFieldsetConfig()
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Product Label'),
                        'componentType' => Fieldset::NAME,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // save data in the product data
                        'provider' => static::DATA_SCOPE_PRODUCT . '_data_source',
                        'ns' => static::FORM_NAME,
                        'collapsible' => true,
                        'sortOrder' => 10,
                        'opened' => true,
                    ],
                ],
            ],
            'children' => [
                static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10),
                static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30),
            ],
        ];
    }

    /**
     * Get config for header container
     *
     * @param int $sortOrder
     * @return array
     */
    protected function getHeaderContainerConfig($sortOrder)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => null,
                        'formElement' => Container::NAME,
                        'componentType' => Container::NAME,
                        'template' => 'ui/form/components/complex',
                        'sortOrder' => $sortOrder,

                    ],
                ],
            ],
            'children' => [],
        ];
    }

    /**
     * Example select field config
     *
     * @param $sortOrder
     * @return array
     */
  protected function getSelectFieldConfig($sortOrder)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Product Labels'),
                        'componentType' => Field::NAME,
                        'formElement' => Select::NAME,
                        'dataScope' => static::FIELD_NAME_SELECT,
                        'dataType' => Text::NAME,
                        'sortOrder' => $sortOrder,
                        'options' => $this->_getOptions(),
                        'visible' => true,
                        'disabled' => false,
                    ],
                ],
            ],
        ];
    }

    /**
     * Get example options as an option array:
     *      [
     *          label => string,
     *          value => option_id
     *      ]
     *
     * @return array
     */
    protected function _getOptions()
    {
        $collection = $this->productlabelModel->create();
        $collection->getSelect();

        $optionsArray = array();
        $optionsArray['none'] = 'None';
        foreach($collection as $col){
            $optionsArray[$col->getId()] = $col->getProductTitle();

        }
        $options = [];

        foreach ($optionsArray as $key => $value)
        {
            $options[] = [
                'value' => $key,
                'label' => $value
            ];
        }
        return $options;
    }
}

To save declared app/code/Vendor/Module/etc/adminhtml/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_save_after">
        <observer name="product_label" instance="Vendor\Module\Observer\CatalogProductSavelabelAfterObserver" />
    </event>
</config>

Created the observer’s class in app/code/Vendor/Module/Observer/CatalogProductSavelabelAfterObserver.php:

<?php
namespace Vendor\Module\Observer;

use \Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Event\Observer as EventObserver;
use Vendor\Module\Ui\DataProvider\Product\Form\Modifier\CustomFieldset;

class CatalogProductSavelabelAfterObserver implements ObserverInterface
{   
    protected $productgridModel;

    public function __construct(
        \Vendor\Module\Model\Productgrid $productgridModel
    ) {
        $this->productgridModel = $productgridModel;
    }
    /**
     * @param EventObserver $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        if (!$product) {
            return;
        }

        $productId = $observer->getProduct()->getId();   
        $id = $product->getData(CustomFieldset::FIELD_NAME_SELECT);

        if($id ==  'none'){
            $productCollection = $this->productgridModel->load($productId,'product_id');
            $productCollection->delete();
        }
        $this->productgridModel->setData('label_id',$id);
        $this->productgridModel->setData('product_id',$productId);
        $this->productgridModel->save();
        $this->productgridModel->unsetData();

    }
}

But on editing the same product,the values are not displayed as selected. Hence it is pointing to the first value in the drop down ie,'None'. Please help .

Best Answer

I have face same issue and Below i have puted alternate solution for this issue.

Try Below code you will get your selected option on first position.

public function toOptionArray()
{

    $currentOptionId = 3;
    $optionArray = $this->getOptions();

    if(!empty($optionArray)) 
    {

        foreach ($optionArray as $key => $value) 
        {
            if($value['value']==$currentOptionId) 
            {

                unset($optionArray[$key]);

                $newOpuion['value'] = $value['value'];
                $newOpuion['label'] = $value['label'];

                array_unshift($optionArray, $newOpuion);
            }
        }

        return $optionArray;
    } 
}