Magento – Magento 2: Creating dynamic matrix in new/edit product page

magento2magento2.2productuicomponent

I need to create a custom matrix for every product on Magento 2 product add/edit page. I need to have both the rows and columns to be dynamic so when someone click add button for either row or column there should be a row or column created depending upon his choice.

I tried to find solution for my problem but I don't think Magento 2 supports anything like this however we can only add dynamic rows in Magento 2 but not Dynamic columns either.

So I decided to create a custom block on product page to use third-party extension for achieving my goal and then serializing the matrix data when the save button on product page is clicked and append it to form data somehow and get in my observer/plugin and process it according to my need.

Problems:

  • I tried to add a custom block in Magento 2 product page by this article but I couldn't see that it's rendered on the page (may be some xml related stuff is updated in M2.2).

  • Is there really a way we can do so with Magento2? If no then please suggest me how can I add custom block on product page and how to link the matrix data with product form so when I submit it it can be captured on back-end.

Best Answer

Yes this is possible. Here is how we can add dynamic rows to Product Edit Page:

Add DataProvider class as:

etc\adminhtml\di.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="customTab" xsi:type="array">
            <item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\NewField</item>
            <item name="sortOrder" xsi:type="number">10</item>
        </item>
    </argument>
</arguments>

And add DataProvider at:

Vendor\Module\Ui\DataProvider\Product\Form\Modifier:

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\Ui\Component\Form\Fieldset;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\DynamicRows;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\Form\Element\ActionDelete;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\DataType\Text;
class NewField extends AbstractModifier
{
const FIELD_IS_DELETE = 'is_delete';
const FIELD_SORT_ORDER_NAME = 'sort_order';
const FIELD_NAME_SELECT = 'select_field';

private $locator;
public function __construct(
LocatorInterface $locator
) {
$this->locator = $locator;
}
public function modifyData(array $data)
 {
return $data;
}
public function modifyMeta(array $meta)
{
 $meta = array_replace_recursive(
    $meta,
    [
        'custom_fieldset' => [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Custom Group'),
                        'componentType' => Fieldset::NAME,
                        'dataScope' => 'data.product.custom_fieldset',
                        'collapsible' => true,
                        'sortOrder' => 5,
                    ],
                ],
            ],
            'children' => [
"custom_field" => $this->getSelectTypeGridConfig(10)
],
        ]
    ]
);
return $meta;
}
protected function getSelectTypeGridConfig($sortOrder) {
return [
'arguments' => [
    'data' => [
        'config' => [
            'addButtonLabel' => __('Add Value'),
            'componentType' => DynamicRows::NAME,
            'component' => 'Magento_Ui/js/dynamic-rows/dynamic-rows',
            'additionalClasses' => 'admin__field-wide',
            'deleteProperty' => static::FIELD_IS_DELETE,
            'deleteValue' => '1',
            'renderDefaultRecord' => false,
            'sortOrder' => $sortOrder,
        ],
    ],
],
'children' => [
    'record' => [
        'arguments' => [
            'data' => [
                'config' => [
                    'componentType' => Container::NAME,
                    'component' => 'Magento_Ui/js/dynamic-rows/record',
                    'positionProvider' => static::FIELD_SORT_ORDER_NAME,
                    'isTemplate' => true,
                    'is_collection' => true,
                ],
            ],
        ],
        'children' => [
            static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(1),
            static::FIELD_IS_DELETE => $this->getIsDeleteFieldConfig(3)
            //Add as many fields as you want

        ]
    ]
]
];
}
protected function getSelectFieldConfig($sortOrder)
{
return [
    'arguments' => [
        'data' => [
            'config' => [
                'label' => __('Options Select'),
                'componentType' => Field::NAME,
                'formElement' => Select::NAME,
                'component' => 'Magento_Catalog/js/custom-options-type',
                'elementTmpl' => 'ui/grid/filters/elements/ui-select',
                // 'selectType' => 'optgroup',
                'dataScope' => static::FIELD_NAME_SELECT,
                'dataType' => Text::NAME,
                'sortOrder' => $sortOrder,
                'options' => $this->_getOptions(),
                'visible' => true,
                'disabled' => false,
            ],
        ],
    ],
];
}
protected function _getOptions()
{
$options = [
    1 => [
        'label' => __('Option 1'),
        'value' => 1
    ],
    2 => [
        'label' => __('Option 2'),
        'value' => 2
    ],
    3 => [
        'label' => __('Option 3'),
        'value' => 3
    ],
];

return $options;
}
protected function getIsDeleteFieldConfig($sortOrder)
{
return [
    'arguments' => [
        'data' => [
            'config' => [
                'componentType' => ActionDelete::NAME,
                'fit' => true,
                'sortOrder' => $sortOrder
            ],
        ],
    ],
];
}
}
Related Topic