Friday, May 9, 2025
  • Home
  • About Us
  • Disclaimer
  • Contact Us
  • Terms & Conditions
  • Privacy Policy
T3llam
  • Home
  • App
  • Mobile
    • IOS
  • Gaming
  • Computing
  • Tech
  • Services & Software
  • Home entertainment
No Result
View All Result
  • Home
  • App
  • Mobile
    • IOS
  • Gaming
  • Computing
  • Tech
  • Services & Software
  • Home entertainment
No Result
View All Result
T3llam
No Result
View All Result
Home Services & Software

Find out how to create product customized attributes utilizing dynamic rows

admin by admin
November 15, 2023
in Services & Software
0
0
SHARES
0
VIEWS
Share on FacebookShare on Twitter


Good day mates on this weblog we are going to learn the way we will create customized attributes in Magento 2 with dynamic rows on the admin add/edit product web page. On this weblog, we are going to cowl every level to create dynamic attributes so keep until the tip.

First, we have to create a primary module.

After creating the module our module construction will look one thing like this.

Module folder structure.
Module Construction

Now create the di.xml file within the and so on folder. This file is used to start out the rendering of the dynamic row attribute when the product add/edit web page opens on the admin finish.

File Path: VendorName/ModuleName/and so on/adminhtml/di.xml

<?xml model="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/and so on/config.xsd">
    <virtualType identify="MagentoCatalogUiDataProviderProductFormModifierPool">
        <arguments>
            <argument identify="modifiers" xsi:kind="array">
                <merchandise identify="add-attributes" xsi:kind="array">
                    <merchandise identify="class" xsi:kind="string">WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute</merchandise>
                    <merchandise identify="sortOrder" xsi:kind="quantity">20</merchandise>
                </merchandise>
            </argument>
        </arguments>
    </virtualType>
</config>

Now we are going to create a UI file that’s really accountable for rendering the attribute with the dynamic rows.

File Path: VendorName/ModuleName/Ui/DataProvider/Product/Type/Modifier/DynamicRowAttribute.php

<?php

namespace WebkulCustomAttributeUiDataProviderProductFormModifier;

use MagentoCatalogModelLocatorLocatorInterface;
use MagentoCatalogUiDataProviderProductFormModifierAbstractModifier;
use MagentoUiComponentFormField;
use MagentoUiComponentFormElementInput;
use MagentoUiComponentDynamicRows;
use MagentoUiComponentContainer;
use MagentoUiComponentFormElementDataTypeText;

use MagentoEavModelResourceModelEntityAttributeSetCollectionFactory as AttributeSetCollection;

use MagentoFrameworkStdlibArrayManager;

class DynamicRowAttribute extends AbstractModifier
{
    public const PRODUCT_ATTRIBUTE_CODE = 'dynamic_row_attribute';
    public const FIELD_IS_DELETE = 'is_delete';
    public const FIELD_SORT_ORDER_NAME = 'sort_order';

    /**
     * Dependency Initilization
     *
     * @param LocatorInterface $locator
     * @param AttributeSetCollection $attributeSetCollection
     * @param MagentoFrameworkSerializeSerializerInterface $serializer
     * @param ArrayManager $arrayManager
     */
    public operate __construct(
        personal LocatorInterface $locator,
        protected AttributeSetCollection $attributeSetCollection,
        protected MagentoFrameworkSerializeSerializerInterface $serializer,
        protected ArrayManager $arrayManager,
    ) {
    }

    /**
     * Modify Knowledge
     *
     * @param array $knowledge
     * @return array
     */
    public operate modifyData(array $knowledge)
    {
        $fieldCode = self::PRODUCT_ATTRIBUTE_CODE;

        $mannequin = $this->locator->getProduct();
        $modelId = $model->getId();

        $highlightsData = $model->getDynamicRowAttribute();

        if ($highlightsData) {
            $highlightsData = $this->serializer->unserialize($highlightsData, true);
            $path = $modelId . '/' . self::DATA_SOURCE_DEFAULT . '/' . $fieldCode;
            $knowledge = $this->arrayManager->set($path, $knowledge, $highlightsData);
        }
        return $knowledge;
    }

    /**
     * Modify Meta
     *
     * @param array $meta
     * @return array
     */
    public operate modifyMeta(array $meta)
    {
        $highlightsPath = $this->arrayManager->findPath(
            self::PRODUCT_ATTRIBUTE_CODE,
            $meta,
            null,
            'kids'
        );

        if ($highlightsPath) {
            $meta = $this->arrayManager->merge(
                $highlightsPath,
                $meta,
                $this->initHighlightFieldStructure($meta, $highlightsPath)
            );
            $meta = $this->arrayManager->set(
                $this->arrayManager->slicePath($highlightsPath, 0, -3)
                    . '/' . self::PRODUCT_ATTRIBUTE_CODE,
                $meta,
                $this->arrayManager->get($highlightsPath, $meta)
            );
            $meta = $this->arrayManager->take away(
                $this->arrayManager->slicePath($highlightsPath, 0, -2),
                $meta
            );
        }

        return $meta;
    }

    /**
     * Add Attribute Grid Config
     *
     * @param int $sortOrder
     * @return array
     */
    protected operate addAttributeGridConfig($sortOrder)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'addButtonLabel' => __('Add Attribute'),
                        '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,
                    ],
                ],
            ],
            'kids' => [
                '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,
                            ],
                        ],
                    ],
                    'kids' => [
                        'attribute_type' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => Field::NAME,
                                        'formElement' => Input::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Attribute Type'),
                                        'enableLabel' => true,
                                        'dataScope' => 'attribute_type',
                                        'sortOrder' => 40,
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                ],
                            ],
                        ],
                        'attribute_lable' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => Field::NAME,
                                        'formElement' => Input::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Attribute'),
                                        'enableLabel' => true,
                                        'dataScope' => 'attribute_lable',
                                        'sortOrder' => 40,
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                ],
                            ],
                        ],
                        'actionDelete' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => 'actionDelete',
                                        'dataType' => Text::NAME,
                                        'label' => '',
                                        'sortOrder' => 50,
                                    ],
                                ],
                            ],
                        ],
                    ]
                ]
            ]
        ];
    }

    /**
     * Get attraction highlights dynamic rows construction
     *
     * @param array $meta
     * @param string $highlightsPath
     * @return array
     */
    protected operate initHighlightFieldStructure($meta, $highlightsPath)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'componentType' => 'dynamicRows',
                        'label' => __('Custom Dynamic Rows'),
                        'renderDefaultRecord' => false,
                        'recordTemplate' => 'record',
                        'dataScope' => '',
                        'dndConfig' => [
                            'enabled' => false,
                        ],
                        'disabled' => false,
                        'sortOrder' =>
                        $this->arrayManager->get($highlightsPath . '/arguments/knowledge/config/sortOrder', $meta),
                    ],
                ],
            ],
            'kids' => [
                'record' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'componentType' => Container::NAME,
                                'isTemplate' => true,
                                'is_collection' => true,
                                'component' => 'Magento_Ui/js/dynamic-rows/record',
                                'dataScope' => '',
                            ],
                        ],
                    ],
                    'kids' => [
                        'title' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'formElement' => Input::NAME,
                                        'componentType' => Field::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Title'),
                                        'dataScope' => 'title',
                                        'require' => '1',
                                    ],
                                ],
                            ],
                        ],

                        'worth' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'formElement' => Input::NAME,
                                        'componentType' => Field::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Value'),
                                        'dataScope' => 'value',
                                        'require' => '1',
                                    ],
                                ],
                            ],
                        ],
                        'actionDelete' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => 'actionDelete',
                                        'dataType' => Text::NAME,
                                        'label' => '',
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }
}

Now we are going to create a brand new file to create the product attribute that shops the information of the dynamic rows within the JSON format.

File Path: VendorNameModuleNameSetupPatchDataProductAttribute.php

<?php

namespace WebkulCustomAttributeSetupPatchData;

use MagentoFrameworkSetupModuleDataSetupInterface;
use MagentoFrameworkSetupPatchDataPatchInterface;
use MagentoCatalogSetupCategorySetupFactory;
use MagentoEavSetupEavSetupFactory;
use WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute;
use MagentoEavModelEntityAttributeScopedAttributeInterface;

class ProductAttribute implements DataPatchInterface
{
    /**
     * Dependency Initilization
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param CategorySetupFactory $categorySetupFactory
     * @param EavSetupFactory $eavSetupFactory
     */
    public operate __construct(
        personal ModuleDataSetupInterface $moduleDataSetup,
        personal CategorySetupFactory $categorySetupFactory,
        personal EavSetupFactory $eavSetupFactory
    ) {
    }

    /**
     * @inheritdoc
     */
    public operate apply()
    {
        $eavSetup = $this->eavSetupFactory->create();
        $eavSetup->addAttribute(
            MagentoCatalogModelProduct::ENTITY,
            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,
            [
                'label' => 'Custom Dynamic Rows',
                'type'  => 'text',
                'default'  => '',
                'input' => 'text',
                'required' => false,
                'sort_order' => 1,
                'user_defined' => true,
                'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
                'used_in_product_listing' => true,
                'visible_on_front' => true,
                'visible' => true
            ]
        );
        $eavSetup->addAttributeToGroup(
            MagentoCatalogModelProduct::ENTITY,
            'Default',
            'Normal', // group
            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,
            1000 // type order
        );
    }

    /**
     * @inheritdoc
     */
    public static operate getDependencies()
    {
        return [];
    }

    /**
     * @inheritdoc
     */
    public operate getAliases()
    {
        return [];
    }
}

Until now our Dynamic Row Attribute will look one thing like this.

Dynamic rows not visible after saving the product.

However wait if we save our product now our dynamic row values is not going to save and easily disappear. So to avoid wasting these dynamic row values we have to add an observer to the occasion catalog_product_save_before that can save the dynamic row worth in our created product dynamic row attribute.

So, now we are going to create our occasion and observer file to avoid wasting our dynamic rows worth.

Occasion File Path: VendorNameModuleNameetcevents.xml

<?xml model="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Occasion/and so on/occasions.xsd">
    <occasion identify="catalog_product_save_before">
        <observer identify="product_dynamic_row_attribute" occasion="WebkulCustomAttributeObserverSaveDynamicRowValues" />
    </occasion>
</config>

Observer File Path: VendorNameModuleNameObserverSaveDynamicRowValues.php

<?php

namespace WebkulCustomAttributeObserver;

use WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute;
use MagentoFrameworkEventObserver;
use MagentoFrameworkEventObserverInterface;
use MagentoFrameworkAppRequestInterface;

class SaveDynamicRowValues implements ObserverInterface
{
    /**
     * Dependency Initilization
     *
     * @param RequestInterface $request
     * @param MagentoFrameworkSerializeSerializerInterface $serializer
     */
    public operate __construct(
        protected RequestInterface $request,
        protected MagentoFrameworkSerializeSerializerInterface $serializer,
    ) {
    }

    /**
     * Execute
     *
     * @param Observer $observer
     * @return this
     */
    public operate execute(Observer $observer)
    {
        /** @var $product MagentoCatalogModelProduct */
        $product = $observer->getEvent()->getDataObject();
        $wholeRequest = $this->request->getPost();
        $submit = $wholeRequest['product'];

        if (empty($submit)) {
            $submit = !empty($wholeRequest['variables']['product']) ? $wholeRequest['variables']['product'] : [];
        }
        $highlights = isset(
            $submit[DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE]
        ) ? $submit[DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE] : '';

        $product->setDynamicRowAttribute($highlights);
        $requiredParams = ['title', 'value'];
        if (is_array($highlights)) {
            $highlights = $this->removeEmptyArray($highlights, $requiredParams);
            $product->setDynamicRowAttribute($this->serializer->serialize($highlights));
        }
    }

    /**
     * Perform to take away empty array from the multi dimensional array
     *
     * @param array $attractionData
     * @param array $requiredParams
     * @return array
     */
    personal operate removeEmptyArray($attractionData, $requiredParams)
    {
        $requiredParams = array_combine($requiredParams, $requiredParams);
        $reqCount = rely($requiredParams);

        foreach ($attractionData as $key => $values) {
            $values = array_filter($values);
            $intersectCount = rely(array_intersect_key($values, $requiredParams));
            if ($reqCount !== $intersectCount) {
                unset($attractionData[$key]);
            }
        }
        return $attractionData;
    }
}

Now after saving once more the Dynamic Rows values will look one thing like this.

Dynamic rows visible after saving the product.

That’s all it’s essential create the product dynamic rows attribute on the admin finish. Hope this can assist.

File construction: until now

File structure till now.
File Construction

It’s possible you’ll go to different Magento 2 tutorials on the Webkul weblog. We additionally supply end-to-end providers on Magento 2 and We’re an Adobe commerce associate as effectively. Additionally, you could Rent a Magento Developer for devoted customization providers.

Thanks 🙂

author-thumb


Deepesh Kumar
3 Badges

15 November 2023

RelatedPosts

Person Information for WooCommerce WhatsApp Order Notifications

Person Information for WooCommerce WhatsApp Order Notifications

April 2, 2025
Report reveals overinflated opinion of infrastructure automation excellence

Report reveals overinflated opinion of infrastructure automation excellence

April 2, 2025
I have been kidnapped by Robert Caro

I have been kidnapped by Robert Caro

April 2, 2025


Good day mates on this weblog we are going to learn the way we will create customized attributes in Magento 2 with dynamic rows on the admin add/edit product web page. On this weblog, we are going to cowl every level to create dynamic attributes so keep until the tip.

First, we have to create a primary module.

After creating the module our module construction will look one thing like this.

Module folder structure.
Module Construction

Now create the di.xml file within the and so on folder. This file is used to start out the rendering of the dynamic row attribute when the product add/edit web page opens on the admin finish.

File Path: VendorName/ModuleName/and so on/adminhtml/di.xml

<?xml model="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/and so on/config.xsd">
    <virtualType identify="MagentoCatalogUiDataProviderProductFormModifierPool">
        <arguments>
            <argument identify="modifiers" xsi:kind="array">
                <merchandise identify="add-attributes" xsi:kind="array">
                    <merchandise identify="class" xsi:kind="string">WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute</merchandise>
                    <merchandise identify="sortOrder" xsi:kind="quantity">20</merchandise>
                </merchandise>
            </argument>
        </arguments>
    </virtualType>
</config>

Now we are going to create a UI file that’s really accountable for rendering the attribute with the dynamic rows.

File Path: VendorName/ModuleName/Ui/DataProvider/Product/Type/Modifier/DynamicRowAttribute.php

<?php

namespace WebkulCustomAttributeUiDataProviderProductFormModifier;

use MagentoCatalogModelLocatorLocatorInterface;
use MagentoCatalogUiDataProviderProductFormModifierAbstractModifier;
use MagentoUiComponentFormField;
use MagentoUiComponentFormElementInput;
use MagentoUiComponentDynamicRows;
use MagentoUiComponentContainer;
use MagentoUiComponentFormElementDataTypeText;

use MagentoEavModelResourceModelEntityAttributeSetCollectionFactory as AttributeSetCollection;

use MagentoFrameworkStdlibArrayManager;

class DynamicRowAttribute extends AbstractModifier
{
    public const PRODUCT_ATTRIBUTE_CODE = 'dynamic_row_attribute';
    public const FIELD_IS_DELETE = 'is_delete';
    public const FIELD_SORT_ORDER_NAME = 'sort_order';

    /**
     * Dependency Initilization
     *
     * @param LocatorInterface $locator
     * @param AttributeSetCollection $attributeSetCollection
     * @param MagentoFrameworkSerializeSerializerInterface $serializer
     * @param ArrayManager $arrayManager
     */
    public operate __construct(
        personal LocatorInterface $locator,
        protected AttributeSetCollection $attributeSetCollection,
        protected MagentoFrameworkSerializeSerializerInterface $serializer,
        protected ArrayManager $arrayManager,
    ) {
    }

    /**
     * Modify Knowledge
     *
     * @param array $knowledge
     * @return array
     */
    public operate modifyData(array $knowledge)
    {
        $fieldCode = self::PRODUCT_ATTRIBUTE_CODE;

        $mannequin = $this->locator->getProduct();
        $modelId = $model->getId();

        $highlightsData = $model->getDynamicRowAttribute();

        if ($highlightsData) {
            $highlightsData = $this->serializer->unserialize($highlightsData, true);
            $path = $modelId . '/' . self::DATA_SOURCE_DEFAULT . '/' . $fieldCode;
            $knowledge = $this->arrayManager->set($path, $knowledge, $highlightsData);
        }
        return $knowledge;
    }

    /**
     * Modify Meta
     *
     * @param array $meta
     * @return array
     */
    public operate modifyMeta(array $meta)
    {
        $highlightsPath = $this->arrayManager->findPath(
            self::PRODUCT_ATTRIBUTE_CODE,
            $meta,
            null,
            'kids'
        );

        if ($highlightsPath) {
            $meta = $this->arrayManager->merge(
                $highlightsPath,
                $meta,
                $this->initHighlightFieldStructure($meta, $highlightsPath)
            );
            $meta = $this->arrayManager->set(
                $this->arrayManager->slicePath($highlightsPath, 0, -3)
                    . '/' . self::PRODUCT_ATTRIBUTE_CODE,
                $meta,
                $this->arrayManager->get($highlightsPath, $meta)
            );
            $meta = $this->arrayManager->take away(
                $this->arrayManager->slicePath($highlightsPath, 0, -2),
                $meta
            );
        }

        return $meta;
    }

    /**
     * Add Attribute Grid Config
     *
     * @param int $sortOrder
     * @return array
     */
    protected operate addAttributeGridConfig($sortOrder)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'addButtonLabel' => __('Add Attribute'),
                        '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,
                    ],
                ],
            ],
            'kids' => [
                '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,
                            ],
                        ],
                    ],
                    'kids' => [
                        'attribute_type' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => Field::NAME,
                                        'formElement' => Input::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Attribute Type'),
                                        'enableLabel' => true,
                                        'dataScope' => 'attribute_type',
                                        'sortOrder' => 40,
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                ],
                            ],
                        ],
                        'attribute_lable' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => Field::NAME,
                                        'formElement' => Input::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Attribute'),
                                        'enableLabel' => true,
                                        'dataScope' => 'attribute_lable',
                                        'sortOrder' => 40,
                                        'validation' => [
                                            'required-entry' => true,
                                        ],
                                    ],
                                ],
                            ],
                        ],
                        'actionDelete' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => 'actionDelete',
                                        'dataType' => Text::NAME,
                                        'label' => '',
                                        'sortOrder' => 50,
                                    ],
                                ],
                            ],
                        ],
                    ]
                ]
            ]
        ];
    }

    /**
     * Get attraction highlights dynamic rows construction
     *
     * @param array $meta
     * @param string $highlightsPath
     * @return array
     */
    protected operate initHighlightFieldStructure($meta, $highlightsPath)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'componentType' => 'dynamicRows',
                        'label' => __('Custom Dynamic Rows'),
                        'renderDefaultRecord' => false,
                        'recordTemplate' => 'record',
                        'dataScope' => '',
                        'dndConfig' => [
                            'enabled' => false,
                        ],
                        'disabled' => false,
                        'sortOrder' =>
                        $this->arrayManager->get($highlightsPath . '/arguments/knowledge/config/sortOrder', $meta),
                    ],
                ],
            ],
            'kids' => [
                'record' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'componentType' => Container::NAME,
                                'isTemplate' => true,
                                'is_collection' => true,
                                'component' => 'Magento_Ui/js/dynamic-rows/record',
                                'dataScope' => '',
                            ],
                        ],
                    ],
                    'kids' => [
                        'title' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'formElement' => Input::NAME,
                                        'componentType' => Field::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Title'),
                                        'dataScope' => 'title',
                                        'require' => '1',
                                    ],
                                ],
                            ],
                        ],

                        'worth' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'formElement' => Input::NAME,
                                        'componentType' => Field::NAME,
                                        'dataType' => Text::NAME,
                                        'label' => __('Value'),
                                        'dataScope' => 'value',
                                        'require' => '1',
                                    ],
                                ],
                            ],
                        ],
                        'actionDelete' => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'componentType' => 'actionDelete',
                                        'dataType' => Text::NAME,
                                        'label' => '',
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
    }
}

Now we are going to create a brand new file to create the product attribute that shops the information of the dynamic rows within the JSON format.

File Path: VendorNameModuleNameSetupPatchDataProductAttribute.php

<?php

namespace WebkulCustomAttributeSetupPatchData;

use MagentoFrameworkSetupModuleDataSetupInterface;
use MagentoFrameworkSetupPatchDataPatchInterface;
use MagentoCatalogSetupCategorySetupFactory;
use MagentoEavSetupEavSetupFactory;
use WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute;
use MagentoEavModelEntityAttributeScopedAttributeInterface;

class ProductAttribute implements DataPatchInterface
{
    /**
     * Dependency Initilization
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param CategorySetupFactory $categorySetupFactory
     * @param EavSetupFactory $eavSetupFactory
     */
    public operate __construct(
        personal ModuleDataSetupInterface $moduleDataSetup,
        personal CategorySetupFactory $categorySetupFactory,
        personal EavSetupFactory $eavSetupFactory
    ) {
    }

    /**
     * @inheritdoc
     */
    public operate apply()
    {
        $eavSetup = $this->eavSetupFactory->create();
        $eavSetup->addAttribute(
            MagentoCatalogModelProduct::ENTITY,
            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,
            [
                'label' => 'Custom Dynamic Rows',
                'type'  => 'text',
                'default'  => '',
                'input' => 'text',
                'required' => false,
                'sort_order' => 1,
                'user_defined' => true,
                'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
                'used_in_product_listing' => true,
                'visible_on_front' => true,
                'visible' => true
            ]
        );
        $eavSetup->addAttributeToGroup(
            MagentoCatalogModelProduct::ENTITY,
            'Default',
            'Normal', // group
            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,
            1000 // type order
        );
    }

    /**
     * @inheritdoc
     */
    public static operate getDependencies()
    {
        return [];
    }

    /**
     * @inheritdoc
     */
    public operate getAliases()
    {
        return [];
    }
}

Until now our Dynamic Row Attribute will look one thing like this.

Dynamic rows not visible after saving the product.

However wait if we save our product now our dynamic row values is not going to save and easily disappear. So to avoid wasting these dynamic row values we have to add an observer to the occasion catalog_product_save_before that can save the dynamic row worth in our created product dynamic row attribute.

So, now we are going to create our occasion and observer file to avoid wasting our dynamic rows worth.

Occasion File Path: VendorNameModuleNameetcevents.xml

<?xml model="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Occasion/and so on/occasions.xsd">
    <occasion identify="catalog_product_save_before">
        <observer identify="product_dynamic_row_attribute" occasion="WebkulCustomAttributeObserverSaveDynamicRowValues" />
    </occasion>
</config>

Observer File Path: VendorNameModuleNameObserverSaveDynamicRowValues.php

<?php

namespace WebkulCustomAttributeObserver;

use WebkulCustomAttributeUiDataProviderProductFormModifierDynamicRowAttribute;
use MagentoFrameworkEventObserver;
use MagentoFrameworkEventObserverInterface;
use MagentoFrameworkAppRequestInterface;

class SaveDynamicRowValues implements ObserverInterface
{
    /**
     * Dependency Initilization
     *
     * @param RequestInterface $request
     * @param MagentoFrameworkSerializeSerializerInterface $serializer
     */
    public operate __construct(
        protected RequestInterface $request,
        protected MagentoFrameworkSerializeSerializerInterface $serializer,
    ) {
    }

    /**
     * Execute
     *
     * @param Observer $observer
     * @return this
     */
    public operate execute(Observer $observer)
    {
        /** @var $product MagentoCatalogModelProduct */
        $product = $observer->getEvent()->getDataObject();
        $wholeRequest = $this->request->getPost();
        $submit = $wholeRequest['product'];

        if (empty($submit)) {
            $submit = !empty($wholeRequest['variables']['product']) ? $wholeRequest['variables']['product'] : [];
        }
        $highlights = isset(
            $submit[DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE]
        ) ? $submit[DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE] : '';

        $product->setDynamicRowAttribute($highlights);
        $requiredParams = ['title', 'value'];
        if (is_array($highlights)) {
            $highlights = $this->removeEmptyArray($highlights, $requiredParams);
            $product->setDynamicRowAttribute($this->serializer->serialize($highlights));
        }
    }

    /**
     * Perform to take away empty array from the multi dimensional array
     *
     * @param array $attractionData
     * @param array $requiredParams
     * @return array
     */
    personal operate removeEmptyArray($attractionData, $requiredParams)
    {
        $requiredParams = array_combine($requiredParams, $requiredParams);
        $reqCount = rely($requiredParams);

        foreach ($attractionData as $key => $values) {
            $values = array_filter($values);
            $intersectCount = rely(array_intersect_key($values, $requiredParams));
            if ($reqCount !== $intersectCount) {
                unset($attractionData[$key]);
            }
        }
        return $attractionData;
    }
}

Now after saving once more the Dynamic Rows values will look one thing like this.

Dynamic rows visible after saving the product.

That’s all it’s essential create the product dynamic rows attribute on the admin finish. Hope this can assist.

File construction: until now

File structure till now.
File Construction

It’s possible you’ll go to different Magento 2 tutorials on the Webkul weblog. We additionally supply end-to-end providers on Magento 2 and We’re an Adobe commerce associate as effectively. Additionally, you could Rent a Magento Developer for devoted customization providers.

Thanks 🙂

author-thumb


Deepesh Kumar
3 Badges

15 November 2023
Previous Post

GM inserts exec at Cruise as security evaluation expands, guide self driving paused

Next Post

Apple offers iPhone 14 customers an additional yr of free emergency SOS by way of satellite tv for pc

Next Post

Apple offers iPhone 14 customers an additional yr of free emergency SOS by way of satellite tv for pc

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • App (3,061)
  • Computing (4,342)
  • Gaming (9,491)
  • Home entertainment (633)
  • IOS (9,408)
  • Mobile (11,737)
  • Services & Software (3,935)
  • Tech (5,253)
  • Uncategorized (4)

Recent Posts

  • Essential Launch Intel You Must Know!
  • New Plex Cellular App With Streamlined Interface Rolling Out to Customers
  • I’ve had it with the present GPU market – and the costs for AMD Radeon companion playing cards on Finest Purchase are why
  • MCP: The brand new “USB-C for AI” that’s bringing fierce rivals collectively
  • Realme GT7’s processor confirmed, launching this month
  • App
  • Computing
  • Gaming
  • Home entertainment
  • IOS
  • Mobile
  • Services & Software
  • Tech
  • Uncategorized
  • Home
  • About Us
  • Disclaimer
  • Contact Us
  • Terms & Conditions
  • Privacy Policy

© 2025 JNews - Premium WordPress news & magazine theme by Jegtheme.

No Result
View All Result
  • Home
  • App
  • Mobile
    • IOS
  • Gaming
  • Computing
  • Tech
  • Services & Software
  • Home entertainment

© 2025 JNews - Premium WordPress news & magazine theme by Jegtheme.

We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies. However you may visit Cookie Settings to provide a controlled consent.
Cookie settingsACCEPT
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analyticsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functionalThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessaryThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-othersThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performanceThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policyThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Save & Accept