{"id":5945,"date":"2016-08-22T13:25:41","date_gmt":"2016-08-22T13:25:41","guid":{"rendered":"https:\/\/blog.mageworx.com\/?p=5945"},"modified":"2023-03-17T10:13:22","modified_gmt":"2023-03-17T10:13:22","slug":"how-to-create-a-modal-window-in-a-custom-field-with-a-code-in-magento-2","status":"publish","type":"post","link":"https:\/\/www.mageworx.com\/blog\/how-to-create-a-modal-window-in-a-custom-field-in-magento-2","title":{"rendered":"How to create a modal window in a custom field with a code in Magento 2"},"content":{"rendered":"\n<!-- SEO Ultimate (http:\/\/www.seodesignsolutions.com\/wordpress-seo\/) - Code Inserter module -->\n<!-- Google Tag Manager (noscript) -->\r\n<noscript><iframe src=\"https:\/\/www.googletagmanager.com\/ns.html?id=GTM-5DTCW7B8\"\r\nheight=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"><\/iframe><\/noscript>\r\n<!-- End Google Tag Manager (noscript) -->\n<!-- \/SEO Ultimate -->\n\n<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 6<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span><p>In this article, we will show\u00a0how to\u00a0create a modal window with\u00a0custom fields and add it to the existing UI form. Moreover, we will show you the example of such a modal in Magento 2. Let&#8217;s begin.<\/p>\n<p><!--more--><\/p>\n<p>First, we need to create a Vendor_Module module:<\/p>\n<p>1. Create a directory <em>app\/code\/Vendor\/Module<\/em><br \/>\n2. Create a registration file <em>app\/code\/Vendor\/Module\/registration.php<\/em> with the following content:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\n\\Magento\\Framework\\Component\\ComponentRegistrar::register(\n    \\Magento\\Framework\\Component\\ComponentRegistrar::MODULE,\n    'Vendor_Module',\n    __DIR__\n);\n?&gt;<\/pre>\n<p>3. Create a composer file (if you plan to transfer the module) <em>app\/code\/Vendor\/Module\/composer.json<\/em> :<\/p>\n<pre class=\"lang:default decode:true \">&lt;script type=\"application\/json\"&gt;\n    {\n        \"name\": \"vendor\/module-module\",\n        \"description\": \"N\/A\",\n        \"require\": {\n            \"php\": \"~5.6.0|~7.0.0\"\n        },\n        \"type\": \"magento2-module\",\n        \"version\": \"2.0.0\",\n        \"license\": [\n            \"OSL-3.0\",\n            \"AFL-3.0\"\n        ],\n        \"autoload\": {\n            \"files\": [\n                \"registration.php\"\n            ],\n            \"psr-4\": {\n                \"Vendor\\\\Module\\\\\": \"\"\n            }\n        }\n    }\n&lt;\/script&gt;<\/pre>\n<p>4. Now, create the module&#8217;s main XML-file <em>app\/code\/Vendor\/Module\/etc\/module.xml<\/em> with the\u00a0dependency from the <em>Magento_Catalog<\/em> module because our modal window will be added to its form:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:Module\/etc\/module.xsd\"&gt;\n    &lt;module name=\"Vendor_Module\" setup_version=\"2.0.0\"&gt;\n        &lt;sequence&gt;\n            &lt;module name=\"Magento_Catalog\"\/&gt;\n        &lt;\/sequence&gt;\n    &lt;\/module&gt;\n&lt;\/config&gt;\n<\/pre>\n<p>The preparation is done. Now, some more details.<\/p>\n<p>You can see the new module in the Magento modules list by entering the following: <em>bin\/magento module:status<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5951\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/1-1.png\" alt=\"\" width=\"315\" height=\"226\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/1-1.png 315w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/1-1-150x108.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/1-1-300x215.png 300w\" sizes=\"auto, (max-width: 315px) 100vw, 315px\" \/>Then, you need to enable it with the following command: <em>bin\/magento module:enable Vendor_Module<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5950\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/2.png\" alt=\"\" width=\"932\" height=\"174\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/2.png 932w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/2-150x28.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/2-300x56.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/2-768x143.png 768w\" sizes=\"auto, (max-width: 932px) 100vw, 932px\" \/>Next, execute <em>bin\/magento setup:upgrade<\/em>. After that, our module should be displayed in the system. However, it contains nothing at the moment. For the code starts working add the following:<\/p>\n<p>Create a file <em>app\/code\/Vendor\/Module\/etc\/adminhtml\/di.xml<\/em>. We are going to place a modifier inside:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:ObjectManager\/etc\/config.xsd\"&gt;\n    &lt;virtualType name=\"Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\Pool\"&gt;\n        &lt;arguments&gt;\n            &lt;argument name=\"modifiers\" xsi:type=\"array\"&gt;\n                &lt;item name=\"custom-options-custom-modal\" xsi:type=\"array\"&gt;\n                    &lt;item name=\"class\" xsi:type=\"string\"&gt;Vendor\\Module\\Ui\\DataProvider\\Product\\Form\\Modifier\\CustomModal&lt;\/item&gt;\n                    &lt;item name=\"sortOrder\" xsi:type=\"number\"&gt;71&lt;\/item&gt;\n                    &lt;!-- Because 70 is sort order of the regular custom options --&gt;\n                &lt;\/item&gt;\n            &lt;\/argument&gt;\n        &lt;\/arguments&gt;\n    &lt;\/virtualType&gt;\n&lt;\/config&gt;<\/pre>\n<p>The modifier is responsible for data addition and some manipulations with elements and UI-form components. There are 2 main methods that came from the modifier&#8217;s interface (they should always present):<\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\n\/**\n * Copyright \u00a9 2016 Magento. All rights reserved.\n * See COPYING.txt for license details.\n *\/\nnamespace Magento\\Ui\\DataProvider\\Modifier;\n\n\/**\n * Class ModifierInterface\n *\/\ninterface ModifierInterface\n{\n    \/**\n     * @param array $data\n     * @return array\n     *\/\n    public function modifyData(array $data);\n\n    \/**\n     * @param array $meta\n     * @return array\n     *\/\n    public function modifyMeta(array $meta);\n}\n?&gt;<\/pre>\n<p>We can add any data to our UI-form in the <em>modifyData<\/em> method or we can delete\/modify the existing product data during the form creation. All the existing UI-form data will be displayed in the input value. Pay attention to the Sort Order of your modifier. A lot of data can be added to\u00a0the following modifier.<\/p>\n<p>We can add our UI components and elements in the <em>modifyMeta<\/em> method. In the example below we are going to add a simple modal window to the custom options fieldset with multiple elements.<\/p>\n<p>Our modifier will be inherited from an abstract modifier for the <em>Catalog_Product<\/em> (<em>vendor\/magento\/module-catalog\/Ui\/DataProvider\/Product\/Form\/Modifier\/AbstractModifier.php<\/em>) module and will be located\u00a0here: <em>app\/code\/Vendor\/Module\/Ui\/DataProvider\/Product\/Form\/Modifier\/CustomModal.php<\/em><\/p>\n<p>Note! You can find the available UI components here: <em>vendor\/magento\/module-ui\/Component<\/em>. It will be useful to look through the subfolders and see what the default <em>Magento_UI<\/em> module provides, before start utilizing it.<\/p>\n<p>Let&#8217;s fill in our modifier&#8217;s file with the base content (namespace, class name, etc):<\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\nnamespace Vendor\\Module\\Ui\\DataProvider\\Product\\Form\\Modifier;\n\nuse Magento\\Catalog\\Model\\Locator\\LocatorInterface;\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\AbstractModifier;\nuse Magento\\Framework\\Stdlib\\ArrayManager;\nuse Magento\\Framework\\UrlInterface;\n\nclass CustomModal extends AbstractModifier\n{\n\n    \/**\n     * @var \\Magento\\Catalog\\Model\\Locator\\LocatorInterface\n     *\/\n    protected $locator;\n\n    \/**\n     * @var ArrayManager\n     *\/\n    protected $arrayManager;\n\n    \/**\n     * @var UrlInterface\n     *\/\n    protected $urlBuilder;\n\n    \/**\n     * @var array\n     *\/\n    protected $meta = [];\n\n    \/**\n     * @param LocatorInterface $locator\n     * @param ArrayManager $arrayManager\n     * @param UrlInterface $urlBuilder\n     *\/\n    public function __construct(\n        LocatorInterface $locator,\n        ArrayManager $arrayManager,\n        UrlInterface $urlBuilder\n    ) {\n        $this-&gt;locator = $locator;\n        $this-&gt;arrayManager = $arrayManager;\n        $this-&gt;urlBuilder = $urlBuilder;\n    }\n\n    public function modifyData(array $data)\n    {\n        return $data;\n    }\n\n    public function modifyMeta(array $meta)\n    {\n        $this-&gt;meta = $meta;\n\n        return $this-&gt;meta;\n    }\n}\n?&gt;<\/pre>\n<p>Now, it should be processed without\u00a0any changes. Then, add the first UI-form element, a link, a modal window that should be called after hitting the link, and multiple fields to the modal window&#8217;s container.<\/p>\n<p><!--?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\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\CustomOptions; use Magento\\Framework\\Stdlib\\ArrayManager; use Magento\\Framework\\UrlInterface; use Magento\\Ui\\Component\\Container; use Magento\\Ui\\Component\\Form\\Fieldset; use Magento\\Ui\\Component\\Modal; 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 CustomModal extends AbstractModifier { const CUSTOM_MODAL_LINK = 'custom_modal_link'; const CUSTOM_MODAL_INDEX = 'custom_modal'; const CUSTOM_MODAL_CONTENT = 'content'; const CUSTOM_MODAL_FIELDSET = 'fieldset'; const CONTAINER_HEADER_NAME = 'header'; const FIELD_NAME_1 = 'field1'; const FIELD_NAME_2 = 'field2'; const FIELD_NAME_3 = 'field3'; \/** * @var \\Magento\\Catalog\\Model\\Locator\\LocatorInterface *\/ protected $locator; \/** * @var ArrayManager *\/ protected $arrayManager; \/** * @var UrlInterface *\/ protected $urlBuilder; \/** * @var array *\/ protected $meta = []; \/** * @param LocatorInterface $locator * @param ArrayManager $arrayManager * @param UrlInterface $urlBuilder *\/ public function __construct( LocatorInterface $locator, ArrayManager $arrayManager, UrlInterface $urlBuilder ) { $this-&gt;locator = $locator;&lt;br ?--><\/p>\n<pre class=\"lang:default decode:true \">&lt;?php\nnamespace Vendor\\Module\\Ui\\DataProvider\\Product\\Form\\Modifier;\n\nuse Magento\\Catalog\\Model\\Locator\\LocatorInterface;\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\AbstractModifier;\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\CustomOptions;\nuse Magento\\Framework\\Stdlib\\ArrayManager;\nuse Magento\\Framework\\UrlInterface;\nuse Magento\\Ui\\Component\\Container;\nuse Magento\\Ui\\Component\\Form\\Fieldset;\nuse Magento\\Ui\\Component\\Modal;\nuse Magento\\Ui\\Component\\Form\\Element\\DataType\\Number;\nuse Magento\\Ui\\Component\\Form\\Element\\DataType\\Text;\nuse Magento\\Ui\\Component\\Form\\Element\\Input;\nuse Magento\\Ui\\Component\\Form\\Element\\Select;\nuse Magento\\Ui\\Component\\Form\\Element\\MultiSelect;\nuse Magento\\Ui\\Component\\Form\\Field;\n\nclass CustomModal extends AbstractModifier\n{\n\n    const CUSTOM_MODAL_LINK = 'custom_modal_link';\n    const CUSTOM_MODAL_INDEX = 'custom_modal';\n    const CUSTOM_MODAL_CONTENT = 'content';\n    const CUSTOM_MODAL_FIELDSET = 'fieldset';\n    const CONTAINER_HEADER_NAME = 'header';\n\n    const FIELD_NAME_1 = 'field1';\n    const FIELD_NAME_2 = 'field2';\n    const FIELD_NAME_3 = 'field3';\n\n    \/**\n     * @var \\Magento\\Catalog\\Model\\Locator\\LocatorInterface\n     *\/\n    protected $locator;\n\n    \/**\n     * @var ArrayManager\n     *\/\n    protected $arrayManager;\n\n    \/**\n     * @var UrlInterface\n     *\/\n    protected $urlBuilder;\n\n    \/**\n     * @var array\n     *\/\n    protected $meta = [];\n\n    \/**\n     * @param LocatorInterface $locator\n     * @param ArrayManager $arrayManager\n     * @param UrlInterface $urlBuilder\n     *\/\n    public function __construct(\n        LocatorInterface $locator,\n        ArrayManager $arrayManager,\n        UrlInterface $urlBuilder\n    ) {\n        $this-&gt;locator = $locator;\n        $this-&gt;arrayManager = $arrayManager;\n        $this-&gt;urlBuilder = $urlBuilder;\n    }\n\n    public function modifyData(array $data)\n    {\n        return $data;\n    }\n\n    public function modifyMeta(array $meta)\n    {\n        $this-&gt;meta = $meta;\n        $this-&gt;addCustomModal();\n        $this-&gt;addCustomModalLink(10);\n\n        return $this-&gt;meta;\n    }\n\n    protected function addCustomModal()\n    {\n        $this-&gt;meta = array_merge_recursive(\n            $this-&gt;meta,\n            [\n                static::CUSTOM_MODAL_INDEX =&gt; $this-&gt;getModalConfig(),\n            ]\n        );\n    }\n\n    protected function getModalConfig()\n    {\n        return [\n            'arguments' =&gt; [\n                'data' =&gt; [\n                    'config' =&gt; [\n                        'componentType' =&gt; Modal::NAME,\n                        'dataScope' =&gt; '',\n                        'provider' =&gt; static::FORM_NAME . '.product_form_data_source',\n                        'ns' =&gt; static::FORM_NAME,\n                        'options' =&gt; [\n                            'title' =&gt; __('Modal Title'),\n                            'buttons' =&gt; [\n                                [\n                                    'text' =&gt; __('Save'),\n                                    'class' =&gt; 'action-primary', \/\/ additional class\n                                    'actions' =&gt; [\n                                        [\n                                            'targetName' =&gt; 'index = product_form', \/\/ Element selector\n                                            'actionName' =&gt; 'save', \/\/ Save parent form (product)\n                                        ],\n                                        'closeModal', \/\/ method name\n                                    ],\n                                ],\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n            'children' =&gt; [\n                static::CUSTOM_MODAL_CONTENT =&gt; [\n                    'arguments' =&gt; [\n                        'data' =&gt; [\n                            'config' =&gt; [\n                                'autoRender' =&gt; false,\n                                'componentType' =&gt; 'container',\n                                'dataScope' =&gt; 'data.product', \/\/ save data in the product data\n                                'externalProvider' =&gt; 'data.product_data_source',\n                                'ns' =&gt; static::FORM_NAME,\n                                'render_url' =&gt; $this-&gt;urlBuilder-&gt;getUrl('mui\/index\/render'),\n                                'realTimeLink' =&gt; true,\n                                'behaviourType' =&gt; 'edit',\n                                'externalFilterMode' =&gt; true,\n                                'currentProductId' =&gt; $this-&gt;locator-&gt;getProduct()-&gt;getId(),\n                            ],\n                        ],\n                    ],\n                    'children' =&gt; [\n                        static::CUSTOM_MODAL_FIELDSET =&gt; [\n                            'arguments' =&gt; [\n                                'data' =&gt; [\n                                    'config' =&gt; [\n                                        'label' =&gt; __('Fieldset'),\n                                        'componentType' =&gt; Fieldset::NAME,\n                                        'dataScope' =&gt; 'custom_data',\n                                        'collapsible' =&gt; true,\n                                        'sortOrder' =&gt; 10,\n                                        'opened' =&gt; true,\n                                    ],\n                                ],\n                            ],\n                            'children' =&gt; [\n                                static::CONTAINER_HEADER_NAME =&gt; $this-&gt;getHeaderContainerConfig(10),\n                                static::FIELD_NAME_1 =&gt; $this-&gt;getFirstFieldConfig(20),\n                                static::FIELD_NAME_2 =&gt; $this-&gt;getSecondFieldConfig(30),\n                                static::FIELD_NAME_3 =&gt; $this-&gt;getThirdFieldConfig(40),\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ];\n    }\n\n    \/**\n     * Get config for header container\n     *\n     * @param int $sortOrder\n     * @return array\n     *\/\n    protected function getHeaderContainerConfig($sortOrder)\n    {\n        return [\n            'arguments' =&gt; [\n                'data' =&gt; [\n                    'config' =&gt; [\n                        'label' =&gt; null,\n                        'formElement' =&gt; Container::NAME,\n                        'componentType' =&gt; Container::NAME,\n                        'template' =&gt; 'ui\/form\/components\/complex',\n                        'sortOrder' =&gt; $sortOrder,\n                        'content' =&gt; __('You can write any text here'),\n                    ],\n                ],\n            ],\n            'children' =&gt; [],\n        ];\n    }\n\n    protected function getFirstFieldConfig($sortOrder)\n    {\n        return [\n            'arguments' =&gt; [\n                'data' =&gt; [\n                    'config' =&gt; [\n                        'label' =&gt; __('Example Text Field'),\n                        'formElement' =&gt; Field::NAME,\n                        'componentType' =&gt; Input::NAME,\n                        'dataScope' =&gt; static::FIELD_NAME_1,\n                        'dataType' =&gt; Number::NAME,\n                        'sortOrder' =&gt; $sortOrder,\n                    ],\n                ],\n            ],\n        ];\n    }\n\n    protected function getSecondFieldConfig($sortOrder)\n    {\n        return [\n            'arguments' =&gt; [\n                'data' =&gt; [\n                    'config' =&gt; [\n                        'label' =&gt; __('Product Options Select'),\n                        'componentType' =&gt; Field::NAME,\n                        'formElement' =&gt; Select::NAME,\n                        'dataScope' =&gt; static::FIELD_NAME_2,\n                        'dataType' =&gt; Text::NAME,\n                        'sortOrder' =&gt; $sortOrder,\n                        'options' =&gt; $this-&gt;_getOptions(),\n                        'visible' =&gt; true,\n                        'disabled' =&gt; false,\n                    ],\n                ],\n            ],\n        ];\n    }\n\n    protected function getThirdFieldConfig($sortOrder)\n    {\n        return [\n            'arguments' =&gt; [\n                'data' =&gt; [\n                    'config' =&gt; [\n                        'label' =&gt; __('Product Options Multiselect'),\n                        'componentType' =&gt; Field::NAME,\n                        'formElement' =&gt; MultiSelect::NAME,\n                        'dataScope' =&gt; static::FIELD_NAME_3,\n                        'dataType' =&gt; Text::NAME,\n                        'sortOrder' =&gt; $sortOrder,\n                        'options' =&gt; $this-&gt;_getOptions(),\n                        'visible' =&gt; true,\n                        'disabled' =&gt; false,\n                    ],\n                ],\n            ],\n        ];\n    }\n\n    \/**\n     * Get all product options as an option array:\n     *      option_id =&gt; [\n     *          label =&gt; string,\n     *          value =&gt; option_id\n     *      ]\n     *\n     * @return array\n     *\/\n    protected function _getOptions()\n    {\n        $options = [];\n        $productOptions = $this-&gt;locator-&gt;getProduct()-&gt;getOptions() ?: [];\n\n        \/** @var \\Magento\\Catalog\\Model\\Product\\Option $option *\/\n        foreach ($productOptions as $index =&gt; $option) {\n            $options[$index]['label'] = $option-&gt;getTitle();\n            $options[$index]['value'] = $option-&gt;getId();\n        }\n\n        return $options;\n    }\n\n    protected function addCustomModalLink($sortOrder)\n    {\n        $this-&gt;meta = array_replace_recursive(\n            $this-&gt;meta,\n            [\n                CustomOptions::GROUP_CUSTOM_OPTIONS_NAME =&gt; [\n                    'children' =&gt; [\n                        CustomOptions::CONTAINER_HEADER_NAME =&gt; [\n                            'children' =&gt; [\n                                static::CUSTOM_MODAL_LINK =&gt; [\n                                    'arguments' =&gt; [\n                                        'data' =&gt; [\n                                            'config' =&gt; [\n                                                'title' =&gt; __('Open Custom Modal'),\n                                                'formElement' =&gt; Container::NAME,\n                                                'componentType' =&gt; Container::NAME,\n                                                'component' =&gt; 'Magento_Ui\/js\/form\/components\/button',\n                                                'actions' =&gt; [\n                                                    [\n                                                        'targetName' =&gt; 'ns=' . static::FORM_NAME . ', index='\n                                                            . static::CUSTOM_MODAL_INDEX, \/\/ selector\n                                                        'actionName' =&gt; 'openModal', \/\/ method name\n                                                    ],\n                                                ],\n                                                'displayAsLink' =&gt; false,\n                                                'sortOrder' =&gt; $sortOrder,\n                                            ],\n                                        ],\n                                    ],\n                                ],\n                            ],\n                        ],\n                    ],\n                ],\n            ]\n        );\n    }\n}\n?&gt;\n<\/pre>\n<p>When the\u00a0product form is downloaded, Magento will collect all the modifiers and sort them in the chosen order. Then, the modifyData and modifyMeta methods will be called for each modifier. Our link (button) and a modal window will be added at the same moment. The only problem is to save this data because the default saving is used and\u00a0duplicated in our window:<\/p>\n<pre class=\"lang:default decode:true \">'buttons' =&gt; [\n    [\n        'text' =&gt; __('Save'),\n        'class' =&gt; 'action-primary', \/\/ additional class\n        'actions' =&gt; [\n            [\n                'targetName' =&gt; 'index = product_form', \/\/ Element selector\n                'actionName' =&gt; 'save', \/\/ Save parent form (product)\n            ],\n        'closeModal', \/\/ method name\n        ],\n    ],\n],<\/pre>\n<p>and if the selected fields are not in the product, they won&#8217;t be saved. You should use an observer or create your own model for saving and sending data using ajax to override the default saving.<\/p>\n<p>The modal window will look like that:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5952\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16-1024x464.png\" alt=\"\" width=\"1024\" height=\"464\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16-1024x464.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16-150x68.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16-300x136.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16-768x348.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/a553e01b90d3629f9974b9f28ad4fb16.png 1916w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>A button to open the window:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5953\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d-1024x186.png\" alt=\"\" width=\"1024\" height=\"186\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d-1024x186.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d-150x27.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d-300x55.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d-768x140.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/3780c49e8482014c7c31ac14a003430d.png 1805w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>You can change its look from the link to the default button by modifying the line from:<\/p>\n<p><em>&#8216;displayAsLink&#8217; =&gt; true,<\/em><\/p>\n<p>to:<\/p>\n<p><em>&#8216;displayAsLink&#8217; =&gt; false,<\/em><\/p>\n<p>Then, the display will change in the following way:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5954\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c-1024x192.png\" alt=\"\" width=\"1024\" height=\"192\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c-1024x192.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c-150x28.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c-300x56.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c-768x144.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/9743657e6ee8059ac5f3317b85c4404c.png 1820w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>The data from our modal window will be send in the following way during the product saving:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5955\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b-1024x467.png\" alt=\"\" width=\"1024\" height=\"467\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b-1024x467.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b-150x68.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b-300x137.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b-768x350.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/99d6d006888a01dfb802aa7d9221636b.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>in the product saving controller (<em>vendor\/magento\/module-catalog\/Controller\/Adminhtml\/Product\/Save.php<\/em>):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-5956\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed-1024x499.png\" alt=\"\" width=\"1024\" height=\"499\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed-1024x499.png 1024w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed-150x73.png 150w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed-300x146.png 300w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed-768x374.png 768w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2016\/08\/88afd136d7a3f9086313ba8de9bec6ed.png 1897w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/>If you still got questions, feel free to ask them in the comments below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 6<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span>In this article, we will show\u00a0how to\u00a0create a modal window with\u00a0custom fields and add it to the existing UI form. Moreover, we will show you the example of such a modal in Magento 2. Let&#8217;s begin.<\/p>\n","protected":false},"author":15,"featured_media":5836,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[255,425],"tags":[436],"class_list":{"0":"post-5945","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-magento-2","8":"category-magento-how-tos","9":"tag-developer-diaries"},"_links":{"self":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/5945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/comments?post=5945"}],"version-history":[{"count":13,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/5945\/revisions"}],"predecessor-version":[{"id":16570,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/5945\/revisions\/16570"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media\/5836"}],"wp:attachment":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media?parent=5945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/categories?post=5945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/tags?post=5945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}