{"id":411283,"date":"2023-11-15T05:51:12","date_gmt":"2023-11-15T05:51:12","guid":{"rendered":"https:\/\/webkul.com\/blog\/?p=411283"},"modified":"2024-09-24T06:40:47","modified_gmt":"2024-09-24T06:40:47","slug":"create-product-dynamic-row-attribute","status":"publish","type":"post","link":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/","title":{"rendered":"Create product dynamic row attribute  (Magento 2)"},"content":{"rendered":"\n<p>In this blog we will learn how we can create <a href=\"https:\/\/store.webkul.com\/magento2-multi-vendor-custom-attributes.html\">custom attributes<\/a> in Magento 2 with dynamic rows at the admin add\/edit product page. <\/p>\n\n\n\n<p>This blog, will cover each and every point to create dynamic attributes so stay till the end.<\/p>\n\n\n\n<p>First, we need to <a href=\"https:\/\/webkul.com\/blog\/magento-development-01-module-registration\/\">create a basic module<\/a>.<\/p>\n\n\n\n<p>After creating the module our module structure will look something like this.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"599\" height=\"147\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\" alt=\"Module folder structure.\" class=\"wp-image-411291\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png 599w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442-300x74.png 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442-250x61.png 250w\" sizes=\"(max-width: 599px) 100vw, 599px\" loading=\"lazy\" \/><figcaption class=\"wp-element-caption\">Module Structure<\/figcaption><\/figure>\n\n\n\n<p>Now create the di.xml file in the etc folder. This file is used to start the rendering of the dynamic row attribute when the product add\/edit page opens at the admin end.<\/p>\n\n\n\n<p><strong>File Path: <\/strong>VendorName\/ModuleName\/etc\/adminhtml\/di.xml<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">&lt;?xml version=&quot;1.0&quot;?&gt;\n&lt;config xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager\/etc\/config.xsd&quot;&gt;\n    &lt;virtualType name=&quot;Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\Pool&quot;&gt;\n        &lt;arguments&gt;\n            &lt;argument name=&quot;modifiers&quot; xsi:type=&quot;array&quot;&gt;\n                &lt;item name=&quot;add-attributes&quot; xsi:type=&quot;array&quot;&gt;\n                    &lt;item name=&quot;class&quot; xsi:type=&quot;string&quot;&gt;Webkul\\CustomAttribute\\Ui\\DataProvider\\Product\\Form\\Modifier\\DynamicRowAttribute&lt;\/item&gt;\n                    &lt;item name=&quot;sortOrder&quot; xsi:type=&quot;number&quot;&gt;20&lt;\/item&gt;\n                &lt;\/item&gt;\n            &lt;\/argument&gt;\n        &lt;\/arguments&gt;\n    &lt;\/virtualType&gt;\n&lt;\/config&gt;<\/pre>\n\n\n\n<p>Now we will create a UI file that is actually responsible for rendering the attribute with the dynamic rows.<\/p>\n\n\n\n<p><strong>File Path:<\/strong> VendorName\/ModuleName\/Ui\/DataProvider\/Product\/Form\/Modifier\/DynamicRowAttribute.php<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">&lt;?php\n\nnamespace Webkul\\CustomAttribute\\Ui\\DataProvider\\Product\\Form\\Modifier;\n\nuse Magento\\Catalog\\Model\\Locator\\LocatorInterface;\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\AbstractModifier;\nuse Magento\\Ui\\Component\\Form\\Field;\nuse Magento\\Ui\\Component\\Form\\Element\\Input;\nuse Magento\\Ui\\Component\\DynamicRows;\nuse Magento\\Ui\\Component\\Container;\nuse Magento\\Ui\\Component\\Form\\Element\\DataType\\Text;\n\nuse Magento\\Eav\\Model\\ResourceModel\\Entity\\Attribute\\Set\\CollectionFactory as AttributeSetCollection;\n\nuse Magento\\Framework\\Stdlib\\ArrayManager;\n\nclass DynamicRowAttribute extends AbstractModifier\n{\n    public const PRODUCT_ATTRIBUTE_CODE = &#039;dynamic_row_attribute&#039;;\n    public const FIELD_IS_DELETE = &#039;is_delete&#039;;\n    public const FIELD_SORT_ORDER_NAME = &#039;sort_order&#039;;\n\n    \/**\n     * Dependency Initilization\n     *\n     * @param LocatorInterface $locator\n     * @param AttributeSetCollection $attributeSetCollection\n     * @param \\Magento\\Framework\\Serialize\\SerializerInterface $serializer\n     * @param ArrayManager $arrayManager\n     *\/\n    public function __construct(\n        private LocatorInterface $locator,\n        protected AttributeSetCollection $attributeSetCollection,\n        protected \\Magento\\Framework\\Serialize\\SerializerInterface $serializer,\n        protected ArrayManager $arrayManager,\n    ) {\n    }\n\n    \/**\n     * Modify Data\n     *\n     * @param array $data\n     * @return array\n     *\/\n    public function modifyData(array $data)\n    {\n        $fieldCode = self::PRODUCT_ATTRIBUTE_CODE;\n\n        $model = $this-&gt;locator-&gt;getProduct();\n        $modelId = $model-&gt;getId();\n\n        $highlightsData = $model-&gt;getDynamicRowAttribute();\n\n        if ($highlightsData) {\n            $highlightsData = $this-&gt;serializer-&gt;unserialize($highlightsData, true);\n            $path = $modelId . &#039;\/&#039; . self::DATA_SOURCE_DEFAULT . &#039;\/&#039; . $fieldCode;\n            $data = $this-&gt;arrayManager-&gt;set($path, $data, $highlightsData);\n        }\n        return $data;\n    }\n\n    \/**\n     * Modify Meta\n     *\n     * @param array $meta\n     * @return array\n     *\/\n    public function modifyMeta(array $meta)\n    {\n        $highlightsPath = $this-&gt;arrayManager-&gt;findPath(\n            self::PRODUCT_ATTRIBUTE_CODE,\n            $meta,\n            null,\n            &#039;children&#039;\n        );\n\n        if ($highlightsPath) {\n            $meta = $this-&gt;arrayManager-&gt;merge(\n                $highlightsPath,\n                $meta,\n                $this-&gt;initHighlightFieldStructure($meta, $highlightsPath)\n            );\n            $meta = $this-&gt;arrayManager-&gt;set(\n                $this-&gt;arrayManager-&gt;slicePath($highlightsPath, 0, -3)\n                    . &#039;\/&#039; . self::PRODUCT_ATTRIBUTE_CODE,\n                $meta,\n                $this-&gt;arrayManager-&gt;get($highlightsPath, $meta)\n            );\n            $meta = $this-&gt;arrayManager-&gt;remove(\n                $this-&gt;arrayManager-&gt;slicePath($highlightsPath, 0, -2),\n                $meta\n            );\n        }\n\n        return $meta;\n    }\n\n    \/**\n     * Add Attribute Grid Config\n     *\n     * @param int $sortOrder\n     * @return array\n     *\/\n    protected function addAttributeGridConfig($sortOrder)\n    {\n        return &#091;\n            &#039;arguments&#039; =&gt; &#091;\n                &#039;data&#039; =&gt; &#091;\n                    &#039;config&#039; =&gt; &#091;\n                        &#039;addButtonLabel&#039; =&gt; __(&#039;Add Attribute&#039;),\n                        &#039;componentType&#039; =&gt; DynamicRows::NAME,\n                        &#039;component&#039; =&gt; &#039;Magento_Ui\/js\/dynamic-rows\/dynamic-rows&#039;,\n                        &#039;additionalClasses&#039; =&gt; &#039;admin__field-wide&#039;,\n                        &#039;deleteProperty&#039; =&gt; static::FIELD_IS_DELETE,\n                        &#039;deleteValue&#039; =&gt; &#039;1&#039;,\n                        &#039;renderDefaultRecord&#039; =&gt; false,\n                        &#039;sortOrder&#039; =&gt; $sortOrder,\n                    ],\n                ],\n            ],\n            &#039;children&#039; =&gt; &#091;\n                &#039;record&#039; =&gt; &#091;\n                    &#039;arguments&#039; =&gt; &#091;\n                        &#039;data&#039; =&gt; &#091;\n                            &#039;config&#039; =&gt; &#091;\n                                &#039;componentType&#039; =&gt; Container::NAME,\n                                &#039;component&#039; =&gt; &#039;Magento_Ui\/js\/dynamic-rows\/record&#039;,\n                                &#039;positionProvider&#039; =&gt; static::FIELD_SORT_ORDER_NAME,\n                                &#039;isTemplate&#039; =&gt; true,\n                                &#039;is_collection&#039; =&gt; true,\n                            ],\n                        ],\n                    ],\n                    &#039;children&#039; =&gt; &#091;\n                        &#039;attribute_type&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;componentType&#039; =&gt; Field::NAME,\n                                        &#039;formElement&#039; =&gt; Input::NAME,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; __(&#039;Attribute Type&#039;),\n                                        &#039;enableLabel&#039; =&gt; true,\n                                        &#039;dataScope&#039; =&gt; &#039;attribute_type&#039;,\n                                        &#039;sortOrder&#039; =&gt; 40,\n                                        &#039;validation&#039; =&gt; &#091;\n                                            &#039;required-entry&#039; =&gt; true,\n                                        ],\n                                    ],\n                                ],\n                            ],\n                        ],\n                        &#039;attribute_lable&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;componentType&#039; =&gt; Field::NAME,\n                                        &#039;formElement&#039; =&gt; Input::NAME,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; __(&#039;Attribute&#039;),\n                                        &#039;enableLabel&#039; =&gt; true,\n                                        &#039;dataScope&#039; =&gt; &#039;attribute_lable&#039;,\n                                        &#039;sortOrder&#039; =&gt; 40,\n                                        &#039;validation&#039; =&gt; &#091;\n                                            &#039;required-entry&#039; =&gt; true,\n                                        ],\n                                    ],\n                                ],\n                            ],\n                        ],\n                        &#039;actionDelete&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;componentType&#039; =&gt; &#039;actionDelete&#039;,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; &#039;&#039;,\n                                        &#039;sortOrder&#039; =&gt; 50,\n                                    ],\n                                ],\n                            ],\n                        ],\n                    ]\n                ]\n            ]\n        ];\n    }\n\n    \/**\n     * Get attraction highlights dynamic rows structure\n     *\n     * @param array $meta\n     * @param string $highlightsPath\n     * @return array\n     *\/\n    protected function initHighlightFieldStructure($meta, $highlightsPath)\n    {\n        return &#091;\n            &#039;arguments&#039; =&gt; &#091;\n                &#039;data&#039; =&gt; &#091;\n                    &#039;config&#039; =&gt; &#091;\n                        &#039;componentType&#039; =&gt; &#039;dynamicRows&#039;,\n                        &#039;label&#039; =&gt; __(&#039;Custom Dynamic Rows&#039;),\n                        &#039;renderDefaultRecord&#039; =&gt; false,\n                        &#039;recordTemplate&#039; =&gt; &#039;record&#039;,\n                        &#039;dataScope&#039; =&gt; &#039;&#039;,\n                        &#039;dndConfig&#039; =&gt; &#091;\n                            &#039;enabled&#039; =&gt; false,\n                        ],\n                        &#039;disabled&#039; =&gt; false,\n                        &#039;sortOrder&#039; =&gt;\n                        $this-&gt;arrayManager-&gt;get($highlightsPath . &#039;\/arguments\/data\/config\/sortOrder&#039;, $meta),\n                    ],\n                ],\n            ],\n            &#039;children&#039; =&gt; &#091;\n                &#039;record&#039; =&gt; &#091;\n                    &#039;arguments&#039; =&gt; &#091;\n                        &#039;data&#039; =&gt; &#091;\n                            &#039;config&#039; =&gt; &#091;\n                                &#039;componentType&#039; =&gt; Container::NAME,\n                                &#039;isTemplate&#039; =&gt; true,\n                                &#039;is_collection&#039; =&gt; true,\n                                &#039;component&#039; =&gt; &#039;Magento_Ui\/js\/dynamic-rows\/record&#039;,\n                                &#039;dataScope&#039; =&gt; &#039;&#039;,\n                            ],\n                        ],\n                    ],\n                    &#039;children&#039; =&gt; &#091;\n                        &#039;title&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;formElement&#039; =&gt; Input::NAME,\n                                        &#039;componentType&#039; =&gt; Field::NAME,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; __(&#039;Title&#039;),\n                                        &#039;dataScope&#039; =&gt; &#039;title&#039;,\n                                        &#039;require&#039; =&gt; &#039;1&#039;,\n                                    ],\n                                ],\n                            ],\n                        ],\n\n                        &#039;value&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;formElement&#039; =&gt; Input::NAME,\n                                        &#039;componentType&#039; =&gt; Field::NAME,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; __(&#039;Value&#039;),\n                                        &#039;dataScope&#039; =&gt; &#039;value&#039;,\n                                        &#039;require&#039; =&gt; &#039;1&#039;,\n                                    ],\n                                ],\n                            ],\n                        ],\n                        &#039;actionDelete&#039; =&gt; &#091;\n                            &#039;arguments&#039; =&gt; &#091;\n                                &#039;data&#039; =&gt; &#091;\n                                    &#039;config&#039; =&gt; &#091;\n                                        &#039;componentType&#039; =&gt; &#039;actionDelete&#039;,\n                                        &#039;dataType&#039; =&gt; Text::NAME,\n                                        &#039;label&#039; =&gt; &#039;&#039;,\n                                    ],\n                                ],\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ];\n    }\n}<\/pre>\n\n\n\n<p>Now we will create a new file to <a href=\"https:\/\/webkul.com\/blog\/create-custom-product-attribute-set-installer-magento-2\/\">create product attribute<\/a> that stores the data of the dynamic rows in the JSON format.<\/p>\n\n\n\n<p><strong>File Path: <\/strong>VendorName\\ModuleName\\Setup\\Patch\\Data\\ProductAttribute.php<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">&lt;?php\n\nnamespace Webkul\\CustomAttribute\\Setup\\Patch\\Data;\n\nuse Magento\\Framework\\Setup\\ModuleDataSetupInterface;\nuse Magento\\Framework\\Setup\\Patch\\DataPatchInterface;\nuse Magento\\Catalog\\Setup\\CategorySetupFactory;\nuse Magento\\Eav\\Setup\\EavSetupFactory;\nuse Webkul\\CustomAttribute\\Ui\\DataProvider\\Product\\Form\\Modifier\\DynamicRowAttribute;\nuse Magento\\Eav\\Model\\Entity\\Attribute\\ScopedAttributeInterface;\n\nclass ProductAttribute implements DataPatchInterface\n{\n    \/**\n     * Dependency Initilization\n     *\n     * @param ModuleDataSetupInterface $moduleDataSetup\n     * @param CategorySetupFactory $categorySetupFactory\n     * @param EavSetupFactory $eavSetupFactory\n     *\/\n    public function __construct(\n        private ModuleDataSetupInterface $moduleDataSetup,\n        private CategorySetupFactory $categorySetupFactory,\n        private EavSetupFactory $eavSetupFactory\n    ) {\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function apply()\n    {\n        $eavSetup = $this-&gt;eavSetupFactory-&gt;create();\n        $eavSetup-&gt;addAttribute(\n            \\Magento\\Catalog\\Model\\Product::ENTITY,\n            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,\n            &#091;\n                &#039;label&#039; =&gt; &#039;Custom Dynamic Rows&#039;,\n                &#039;type&#039;  =&gt; &#039;text&#039;,\n                &#039;default&#039;  =&gt; &#039;&#039;,\n                &#039;input&#039; =&gt; &#039;text&#039;,\n                &#039;required&#039; =&gt; false,\n                &#039;sort_order&#039; =&gt; 1,\n                &#039;user_defined&#039; =&gt; true,\n                &#039;global&#039; =&gt; ScopedAttributeInterface::SCOPE_GLOBAL,\n                &#039;used_in_product_listing&#039; =&gt; true,\n                &#039;visible_on_front&#039; =&gt; true,\n                &#039;visible&#039; =&gt; true\n            ]\n        );\n        $eavSetup-&gt;addAttributeToGroup(\n            \\Magento\\Catalog\\Model\\Product::ENTITY,\n            &#039;Default&#039;,\n            &#039;General&#039;, \/\/ group\n            DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE,\n            1000 \/\/ sort order\n        );\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public static function getDependencies()\n    {\n        return &#091;];\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function getAliases()\n    {\n        return &#091;];\n    }\n}<\/pre>\n\n\n\n<p>Till now our Dynamic Row Attribute will look something like this.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1200\" height=\"591\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443-1200x591.png\" alt=\"Dynamic rows not visible after saving the product.\" class=\"wp-image-411301\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443-1200x591.png 1200w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443-300x148.png 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443-250x123.png 250w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443-768x378.png 768w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_443.png 1526w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" loading=\"lazy\" \/><\/figure>\n\n\n\n<p>But wait if we save our product now our dynamic row values will not save and simply disappear. <\/p>\n\n\n\n<p>So to save these dynamic row values we need to add an <a href=\"https:\/\/webkul.com\/blog\/use-observer-in-magento\/\">event observer<\/a> to the event <em><strong>catalog_product_save_before<\/strong><\/em> that will save the dynamic row value in our created product dynamic row attribute.<\/p>\n\n\n\n<p>So, now we will create our event and observer file to save our dynamic rows value.<\/p>\n\n\n\n<p><strong>Event File Path: <\/strong>VendorName\\ModuleName\\etc\\events.xml<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">&lt;?xml version=&quot;1.0&quot;?&gt;\n&lt;config xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Event\/etc\/events.xsd&quot;&gt;\n    &lt;event name=&quot;catalog_product_save_before&quot;&gt;\n        &lt;observer name=&quot;product_dynamic_row_attribute&quot; instance=&quot;Webkul\\CustomAttribute\\Observer\\SaveDynamicRowValues&quot; \/&gt;\n    &lt;\/event&gt;\n&lt;\/config&gt;<\/pre>\n\n\n\n<p><strong>Observer File Path: <\/strong>VendorName\\ModuleName\\Observer\\SaveDynamicRowValues.php<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">&lt;?php\n\nnamespace Webkul\\CustomAttribute\\Observer;\n\nuse Webkul\\CustomAttribute\\Ui\\DataProvider\\Product\\Form\\Modifier\\DynamicRowAttribute;\nuse Magento\\Framework\\Event\\Observer;\nuse Magento\\Framework\\Event\\ObserverInterface;\nuse Magento\\Framework\\App\\RequestInterface;\n\nclass SaveDynamicRowValues implements ObserverInterface\n{\n    \/**\n     * Dependency Initilization\n     *\n     * @param RequestInterface $request\n     * @param \\Magento\\Framework\\Serialize\\SerializerInterface $serializer\n     *\/\n    public function __construct(\n        protected RequestInterface $request,\n        protected \\Magento\\Framework\\Serialize\\SerializerInterface $serializer,\n    ) {\n    }\n\n    \/**\n     * Execute\n     *\n     * @param Observer $observer\n     * @return this\n     *\/\n    public function execute(Observer $observer)\n    {\n        \/** @var $product \\Magento\\Catalog\\Model\\Product *\/\n        $product = $observer-&gt;getEvent()-&gt;getDataObject();\n        $wholeRequest = $this-&gt;request-&gt;getPost();\n        $post = $wholeRequest&#091;&#039;product&#039;];\n\n        if (empty($post)) {\n            $post = !empty($wholeRequest&#091;&#039;variables&#039;]&#091;&#039;product&#039;]) ? $wholeRequest&#091;&#039;variables&#039;]&#091;&#039;product&#039;] : &#091;];\n        }\n        $highlights = isset(\n            $post&#091;DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE]\n        ) ? $post&#091;DynamicRowAttribute::PRODUCT_ATTRIBUTE_CODE] : &#039;&#039;;\n\n        $product-&gt;setDynamicRowAttribute($highlights);\n        $requiredParams = &#091;&#039;title&#039;, &#039;value&#039;];\n        if (is_array($highlights)) {\n            $highlights = $this-&gt;removeEmptyArray($highlights, $requiredParams);\n            $product-&gt;setDynamicRowAttribute($this-&gt;serializer-&gt;serialize($highlights));\n        }\n    }\n\n    \/**\n     * Function to remove empty array from the multi dimensional array\n     *\n     * @param array $attractionData\n     * @param array $requiredParams\n     * @return array\n     *\/\n    private function removeEmptyArray($attractionData, $requiredParams)\n    {\n        $requiredParams = array_combine($requiredParams, $requiredParams);\n        $reqCount = count($requiredParams);\n\n        foreach ($attractionData as $key =&gt; $values) {\n            $values = array_filter($values);\n            $intersectCount = count(array_intersect_key($values, $requiredParams));\n            if ($reqCount !== $intersectCount) {\n                unset($attractionData&#091;$key]);\n            }\n        }\n        return $attractionData;\n    }\n}<\/pre>\n\n\n\n<p>Now after saving again the Dynamic Rows values will look something like this.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1200\" height=\"591\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444-1200x591.png\" alt=\"Dynamic rows visible after saving the product.\" class=\"wp-image-411312\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444-1200x591.png 1200w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444-300x148.png 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444-250x123.png 250w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444-768x378.png 768w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_444.png 1526w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" loading=\"lazy\" \/><\/figure>\n\n\n\n<p>That is all you need to create the product dynamic rows attribute at the admin end. Hope this will help.<\/p>\n\n\n\n<p><strong>File structure<\/strong>: till now<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"676\" height=\"413\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_447.png\" alt=\"File structure till now.\" class=\"wp-image-411433\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_447.png 676w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_447-300x183.png 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_447-250x153.png 250w\" sizes=\"(max-width: 676px) 100vw, 676px\" loading=\"lazy\" \/><figcaption class=\"wp-element-caption\">File Structure<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>This blog has provided a comprehensive guide on creating custom attributes with dynamic rows in Magento 2&#8217;s admin add\/edit product page. <\/p>\n\n\n\n<p>By following the steps from setting up a basic module to implementing necessary files such as <code>di.xml<\/code>, UI components, and event observers you can enhance the product management experience. <\/p>\n\n\n\n<p>The dynamic row attributes not only improve data entry flexibility but also ensure that all values are saved correctly. <\/p>\n\n\n\n<p>This tutorial aims to empower you with the knowledge to implement these features seamlessly. <\/p>\n\n\n\n<p>For further learning and assistance, you can explore more Magento 2 tutorials or consider hiring a dedicated Magento developer. Thank you for reading, and happy coding!<\/p>\n\n\n\n<p>You may visit other Magento 2 tutorials on the Webkul blog. We also offer end-to-end services on Magento 2 and We are an Adobe commerce partner as well. <\/p>\n\n\n\n<p>Also, you may&nbsp;<a href=\"https:\/\/webkul.com\/magento-development\/\">Hire Magento Developer<\/a>&nbsp;for dedicated customization services.<\/p>\n\n\n\n<p>Thanks \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog we will learn how we can create custom attributes in Magento 2 with dynamic rows at the admin add\/edit product page. This blog, will cover each and every point to create dynamic attributes so stay till the end. First, we need to create a basic module. After creating the module our module <a href=\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\">[&#8230;]<\/a><\/p>\n","protected":false},"author":548,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9121],"tags":[12967,15157,15158,2460,862],"class_list":["post-411283","post","type-post","status-publish","format-standard","hentry","category-magento-2","tag-adobe-commerce","tag-attribute-dynamic-rows","tag-dynamic-attribute","tag-magento-2","tag-product-attribute"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to create product custom attributes using dynamic rows<\/title>\n<meta name=\"description\" content=\"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to create product custom attributes using dynamic rows\" \/>\n<meta property=\"og:description\" content=\"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\" \/>\n<meta property=\"og:site_name\" content=\"Webkul Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webkul\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-15T05:51:12+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-09-24T06:40:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\" \/>\n<meta name=\"author\" content=\"Deepesh Kumar\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@webkul\" \/>\n<meta name=\"twitter:site\" content=\"@webkul\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Deepesh Kumar\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\"},\"author\":{\"name\":\"Deepesh Kumar\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/43552f90bbc8fafb784fe138f6d82a0b\"},\"headline\":\"Create product dynamic row attribute (Magento 2)\",\"datePublished\":\"2023-11-15T05:51:12+00:00\",\"dateModified\":\"2024-09-24T06:40:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\"},\"wordCount\":456,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/webkul.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\",\"keywords\":[\"Adobe Commerce\",\"Attribute Dynamic Rows\",\"Dynamic Attribute\",\"Magento 2\",\"product attribute\"],\"articleSection\":[\"Magento 2\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\",\"url\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\",\"name\":\"How to create product custom attributes using dynamic rows\",\"isPartOf\":{\"@id\":\"https:\/\/webkul.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\",\"datePublished\":\"2023-11-15T05:51:12+00:00\",\"dateModified\":\"2024-09-24T06:40:47+00:00\",\"description\":\"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.\",\"breadcrumb\":{\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage\",\"url\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\",\"contentUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png\",\"width\":599,\"height\":147,\"caption\":\"Selection_442\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/webkul.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create product dynamic row attribute (Magento 2)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/webkul.com\/blog\/#website\",\"url\":\"https:\/\/webkul.com\/blog\/\",\"name\":\"Webkul Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/webkul.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/webkul.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/webkul.com\/blog\/#organization\",\"name\":\"WebKul Software Private Limited\",\"url\":\"https:\/\/webkul.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png\",\"contentUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png\",\"width\":380,\"height\":380,\"caption\":\"WebKul Software Private Limited\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webkul\/\",\"https:\/\/x.com\/webkul\",\"https:\/\/www.instagram.com\/webkul\/\",\"https:\/\/www.linkedin.com\/company\/webkul\",\"https:\/\/www.youtube.com\/user\/webkul\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/43552f90bbc8fafb784fe138f6d82a0b\",\"name\":\"Deepesh Kumar\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d898f8a790ab5a002f048ad4b4661fda07600235f1338d01ff1fd60152fe4d10?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d898f8a790ab5a002f048ad4b4661fda07600235f1338d01ff1fd60152fe4d10?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g\",\"caption\":\"Deepesh Kumar\"},\"description\":\"Deepesh Kumar, a proficient Software Engineer, excels in PHP, JavaScript, and database management. Mastery of complex eCommerce systems and Magento&rsquo;s architecture drives innovative solutions and optimizes performance for business success.\",\"url\":\"https:\/\/webkul.com\/blog\/author\/deepeshkumar-mg397\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to create product custom attributes using dynamic rows","description":"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/","og_locale":"en_US","og_type":"article","og_title":"How to create product custom attributes using dynamic rows","og_description":"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.","og_url":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/","og_site_name":"Webkul Blog","article_publisher":"https:\/\/www.facebook.com\/webkul\/","article_published_time":"2023-11-15T05:51:12+00:00","article_modified_time":"2024-09-24T06:40:47+00:00","og_image":[{"url":"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png","type":"","width":"","height":""}],"author":"Deepesh Kumar","twitter_card":"summary_large_image","twitter_creator":"@webkul","twitter_site":"@webkul","twitter_misc":{"Written by":"Deepesh Kumar","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#article","isPartOf":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/"},"author":{"name":"Deepesh Kumar","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/43552f90bbc8fafb784fe138f6d82a0b"},"headline":"Create product dynamic row attribute (Magento 2)","datePublished":"2023-11-15T05:51:12+00:00","dateModified":"2024-09-24T06:40:47+00:00","mainEntityOfPage":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/"},"wordCount":456,"commentCount":0,"publisher":{"@id":"https:\/\/webkul.com\/blog\/#organization"},"image":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage"},"thumbnailUrl":"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png","keywords":["Adobe Commerce","Attribute Dynamic Rows","Dynamic Attribute","Magento 2","product attribute"],"articleSection":["Magento 2"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/","url":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/","name":"How to create product custom attributes using dynamic rows","isPartOf":{"@id":"https:\/\/webkul.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage"},"image":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage"},"thumbnailUrl":"https:\/\/webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png","datePublished":"2023-11-15T05:51:12+00:00","dateModified":"2024-09-24T06:40:47+00:00","description":"Hello friends in this blog we will learn how we can create custom attributes in Magento with dynamic rows at the admin add\/edit product page.","breadcrumb":{"@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#primaryimage","url":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png","contentUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2023\/11\/Selection_442.png","width":599,"height":147,"caption":"Selection_442"},{"@type":"BreadcrumbList","@id":"https:\/\/webkul.com\/blog\/create-product-dynamic-row-attribute\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/webkul.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Create product dynamic row attribute (Magento 2)"}]},{"@type":"WebSite","@id":"https:\/\/webkul.com\/blog\/#website","url":"https:\/\/webkul.com\/blog\/","name":"Webkul Blog","description":"","publisher":{"@id":"https:\/\/webkul.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/webkul.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/webkul.com\/blog\/#organization","name":"WebKul Software Private Limited","url":"https:\/\/webkul.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png","contentUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png","width":380,"height":380,"caption":"WebKul Software Private Limited"},"image":{"@id":"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webkul\/","https:\/\/x.com\/webkul","https:\/\/www.instagram.com\/webkul\/","https:\/\/www.linkedin.com\/company\/webkul","https:\/\/www.youtube.com\/user\/webkul\/"]},{"@type":"Person","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/43552f90bbc8fafb784fe138f6d82a0b","name":"Deepesh Kumar","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d898f8a790ab5a002f048ad4b4661fda07600235f1338d01ff1fd60152fe4d10?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d898f8a790ab5a002f048ad4b4661fda07600235f1338d01ff1fd60152fe4d10?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g","caption":"Deepesh Kumar"},"description":"Deepesh Kumar, a proficient Software Engineer, excels in PHP, JavaScript, and database management. Mastery of complex eCommerce systems and Magento&rsquo;s architecture drives innovative solutions and optimizes performance for business success.","url":"https:\/\/webkul.com\/blog\/author\/deepeshkumar-mg397\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/411283","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/users\/548"}],"replies":[{"embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/comments?post=411283"}],"version-history":[{"count":25,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/411283\/revisions"}],"predecessor-version":[{"id":464708,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/411283\/revisions\/464708"}],"wp:attachment":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/media?parent=411283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/categories?post=411283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/tags?post=411283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}