{"id":12868,"date":"2020-11-20T14:44:03","date_gmt":"2020-11-20T14:44:03","guid":{"rendered":"https:\/\/www.mageworx.com\/blog\/?p=12868"},"modified":"2021-10-25T10:07:56","modified_gmt":"2021-10-25T10:07:56","slug":"how-to-add-custom-field-for-option-values-in-advanced-product-options","status":"publish","type":"post","link":"https:\/\/www.mageworx.com\/blog\/how-to-add-custom-field-for-option-values-in-advanced-product-options","title":{"rendered":"How to Add Custom Field for Option Values in Advanced Product Options"},"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>\n<p>From the <a href=\"https:\/\/www.mageworx.com\/blog\/how-to-add-custom-field-to-advanced-product-options-extension\/\">previous article<\/a>, you\u2019ve learned how to create Magento custom option fields. We also have found out how to display the field data on both the product page front-end and the order page in the admin panel.<br><\/p>\n\n\n\n<p>What\u2019s now?<br><\/p>\n\n\n\n<p>Let\u2019s learn how to add the same custom <strong>GTIN<\/strong> field for the option values and display it on the product page front-end.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #1. New Module Creation<\/h2>\n\n\n\n<p>Let\u2019s start with the new module creation, which process was covered in detail in this <a href=\"https:\/\/www.mageworx.com\/blog\/advanced-product-options-customization\/\">Mageworx blog post<\/a>.<br><\/p>\n\n\n\n<p>Thus, without further ado, here is the code that we will need:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. composer.json<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"name\": \"mageworx\/module-optionvaluegtin\",\n    \"description\": \"N\/A\",\n    \"require\": {\n        \"magento\/framework\"     :     \"&gt;=100.1.0 &lt;101\",\n        \"magento\/module-catalog\":     \"&gt;=101.0.0 &lt;104\"\n    },\n    \"type\": \"magento2-module\",\n    \"version\": \"1.0.0\",\n    \"license\": &#91;\n        \"OSL-3.0\",\n        \"AFL-3.0\"\n    ],\n    \"autoload\": {\n        \"files\": &#91;\n            \"registration.php\"\n        ],\n        \"psr-4\": {\n            \"VendorName\\\\OptionValueGtin\\\\\": \"\"\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. etc\/module.xml<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n\n&lt;config xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:Module\/etc\/module.xsd\"&gt;\n    &lt;module name=\"VendorName_OptionValueGtin\" setup_version=\"1.0.0\"&gt;\n        &lt;sequence&gt;\n            &lt;module name=\"Magento_Catalog\"\/&gt;\n            &lt;module name=\"MageWorx_OptionBase\"\/&gt;\n        &lt;\/sequence&gt;\n    &lt;\/module&gt;\n&lt;\/config&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. registration.php<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\\Magento\\Framework\\Component\\ComponentRegistrar::register(\n    \\Magento\\Framework\\Component\\ComponentRegistrar::MODULE,\n    'VendorName_OptionValueGtin',\n    __DIR__\n);\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step #2. Adding New Field to Database<\/h2>\n\n\n\n<p>It\u2019s time to create the <strong>GTIN <\/strong>field and add it to the corresponding table in the database.<br><\/p>\n\n\n\n<p>As we are adding a field for option values, the `catalog_product_option_type_value` table will be required.<br><\/p>\n\n\n\n<p>Let\u2019s create the following file:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/Setup\/InstallSchema.php`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nnamespace VendorName\\OptionValueGtin\\Setup;\n\nuse Magento\\Framework\\Setup\\InstallSchemaInterface;\nuse Magento\\Framework\\Setup\\ModuleContextInterface;\nuse Magento\\Framework\\Setup\\SchemaSetupInterface;\nuse Magento\\Framework\\DB\\Ddl\\Table;\n\nclass InstallSchema implements InstallSchemaInterface\n{\n    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)\n    {\n        $setup-&gt;startSetup();\n\n        $setup-&gt;getConnection()-&gt;addColumn(\n            $setup-&gt;getTable('catalog_product_option_type_value'),\n            'gtin',\n            &#91;\n                'type'     =&gt; Table::TYPE_TEXT,\n                'nullable' =&gt; true,\n                'default'  =&gt; null,\n                'comment'  =&gt; 'Gtin (added by MageWorx Option Value Gtin)',\n            ]\n        );\n\n        $setup-&gt;endSetup();\n\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step #3. Adding Logic to Work with Backend<\/h2>\n\n\n\n<p>Use the <strong>pool-modifier<\/strong> mechanism to Magento add field to custom option.<br><\/p>\n\n\n\n<p>Let\u2019s create the following file:<br><\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/etc\/adminhtml\/di.xml`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n\n&lt;config xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:ObjectManager\/etc\/config.xsd\"&gt;\n    &lt;virtualType name=\"MageWorx\\OptionBase\\Ui\\DataProvider\\Product\\Form\\Modifier\\Pool\"&gt;\n        &lt;arguments&gt;\n            &lt;argument name=\"modifiers\" xsi:type=\"array\"&gt;\n                &lt;item name=\"mageworx-option-value-gtin\" xsi:type=\"array\"&gt;\n                    &lt;item name=\"class\" xsi:type=\"string\"&gt;MageWorx\\OptionValueGtin\\Ui\\DataProvider\\Product\\Form\\Modifier\\OptionValueGtin&lt;\/item&gt;\n                    &lt;item name=\"sortOrder\" xsi:type=\"number\"&gt;72&lt;\/item&gt;\n                &lt;\/item&gt;\n            &lt;\/argument&gt;\n        &lt;\/arguments&gt;\n    &lt;\/virtualType&gt;\n&lt;\/config&gt;\n<\/code><\/pre>\n\n\n\n<p>Here:<\/p>\n\n\n\n<p>We add our modifier to the general pool of the <a href=\"https:\/\/www.mageworx.com\/magento-2-advanced-product-options-suite.html\">Advanced Product Options <\/a>extension for Magento 2\u2015<\/p>\n\n\n\n<p>`MageWorx\\OptionBase\\Ui\\DataProvider\\Product\\Form\\Modifier\\Pool`.<br><\/p>\n\n\n\n<p>`VendorName\\OptionValueGtin\\Ui\\DataProvider\\Product\\Form\\Modifier\\OptionValueGtin` is the modifier class.<br><\/p>\n\n\n\n<p>Below:<\/p>\n\n\n\n<p>See the code that allows adding our field to the `app\/code\/VendorName\/OptionValueGtin\/Ui\/DataProvider\/Product\/Form\/Modifier\/OptionValueGtin.php` form:<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nnamespace VendorName\\OptionValueGtin\\Ui\\DataProvider\\Product\\Form\\Modifier;\n\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\AbstractModifier;\nuse Magento\\Catalog\\Ui\\DataProvider\\Product\\Form\\Modifier\\CustomOptions;\nuse Magento\\Ui\\Component\\Form\\Element\\Input;\nuse Magento\\Ui\\Component\\Form\\Element\\DataType\\Number;\nuse Magento\\Ui\\Component\\Form\\Field;\nuse MageWorx\\OptionBase\\Ui\\DataProvider\\Product\\Form\\Modifier\\ModifierInterface;\n\nclass OptionValueGtin extends AbstractModifier implements ModifierInterface\n{\n    \/**\n     * @var array\n     *\/\n    protected $meta = &#91;];\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function modifyData(array $data)\n    {\n        return $data;\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function modifyMeta(array $meta)\n    {\n        $this-&gt;meta = $meta;\n\n        $this-&gt;addFields();\n\n        return $this-&gt;meta;\n    }\n\n    \/**\n     * Adds fields to the meta-data\n     *\/\n    protected function addFields()\n    {\n        $groupCustomOptionsName    = CustomOptions::GROUP_CUSTOM_OPTIONS_NAME;\n        $optionContainerName       = CustomOptions::CONTAINER_OPTION;\n\n        \/\/ Add fields to the values\n        $valueFeaturesFields   = $this-&gt;getValueFieldsConfig();\n        $this-&gt;meta&#91;$groupCustomOptionsName]&#91;'children']&#91;'options']&#91;'children']&#91;'record']&#91;'children']\n        &#91;$optionContainerName]&#91;'children']&#91;'values']&#91;'children']&#91;'record']&#91;'children'] = array_replace_recursive(\n            $this-&gt;meta&#91;$groupCustomOptionsName]&#91;'children']&#91;'options']&#91;'children']&#91;'record']&#91;'children']\n            &#91;$optionContainerName]&#91;'children']&#91;'values']&#91;'children']&#91;'record']&#91;'children'],\n            $valueFeaturesFields\n        );\n\n    }\n\n\n    \/**\n     * The custom option fields config\n     *\n     * @return array\n     *\/\n    protected function getValueFieldsConfig()\n    {\n        $fields&#91;'gtin'] = $this-&gt;getGtinFieldConfig();\n\n        return $fields;\n    }\n\n    \/**\n     * Get gtin field config\n     *\n     * @return array\n     *\/\n    protected function getGtinFieldConfig()\n    {\n        return &#91;\n            'arguments' =&gt; &#91;\n                'data' =&gt; &#91;\n                    'config' =&gt; &#91;\n                        'label'         =&gt; __('GTIN'),\n                        'componentType' =&gt; Field::NAME,\n                        'formElement'   =&gt; Input::NAME,\n                        'dataType'      =&gt; Number::NAME,\n                        'dataScope'     =&gt; 'gtin',\n                        'sortOrder'     =&gt; 92\n                    ],\n                ],\n            ],\n        ];\n    }\n\n    \/**\n     * Check is current modifier for the product only\n     *\n     * @return bool\n     *\/\n    public function isProductScopeOnly()\n    {\n        return false;\n    }\n\n    \/**\n     * Get sort order of modifier to load modifiers in the right order\n     *\n     * @return int\n     *\/\n    public function getSortOrder()\n    {\n        return 32;\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>Now, install the extension and check that all is done correctly, i.e.,<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>php bin\/magento module:enable VendorName_OptionValueGtin<\/li><li>php bin\/magento setup:upgrade<\/li><li>php bin\/magento cache:flush<\/li><\/ul>\n\n\n\n<p>As you can see, the newly added field gets displayed now:<br><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/DD8N30scC-s1ZicRNTbGSNQoQFnyAL7eNsN81xO8LSMAkzLVtQuHpSFLGBPEXVe6rmpZPWdTkuta1iQ0strJMQUNp_a97sMNkFaVnQJv6Zhx-wtZqkDzkT5tW_JQQXq6NmGtS3MQ\" alt=\"How to add custom fields for products on Magento 2 | Mageworx Blog\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step #4. Adding Setting to Disable GTIN Field Display for Advanced Product Options Config<\/h2>\n\n\n\n<p>What about mixing up our article a little?<br><\/p>\n\n\n\n<p>I offer to add some new functionality\u2015the ability to enable\/disable the <strong>GTIN <\/strong>field display for option values on the product page front-end.&nbsp;<br><\/p>\n\n\n\n<p>You will need to create the file:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/etc\/adminhtml\/system.xml`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:module:Magento_Config:etc\/system_file.xsd\"&gt;\n    &lt;system&gt;\n        &lt;tab id=\"mageworx\" sortOrder=\"2001\"&gt;\n            &lt;label&gt;MageWorx&lt;\/label&gt;\n        &lt;\/tab&gt;\n        &lt;section id=\"mageworx_apo\" translate=\"label\" type=\"text\" sortOrder=\"10\" showInDefault=\"1\" showInWebsite=\"1\" showInStore=\"1\"&gt;\n            &lt;label&gt;&lt;!&#91;CDATA&#91;Advanced Product Options]]&gt;&lt;\/label&gt;\n            &lt;tab&gt;mageworx&lt;\/tab&gt;\n            &lt;resource&gt;VendorName_OptionValueGtin::config_optionvaluegtin&lt;\/resource&gt;\n            &lt;group id=\"optionvaluegtin\" translate=\"label\" type=\"text\" sortOrder=\"100\" showInDefault=\"1\" showInWebsite=\"1\" showInStore=\"1\"&gt;\n                &lt;label&gt;&lt;!&#91;CDATA&#91;Option Value GTIN]]&gt;&lt;\/label&gt;\n                &lt;field id=\"use_optionvaluegtin\" translate=\"label\" type=\"select\" sortOrder=\"80\" showInDefault=\"1\" showInWebsite=\"1\" showInStore=\"1\"&gt;\n                    &lt;label&gt;&lt;!&#91;CDATA&#91;Enable Option's Value 'GTIN']]&gt;&lt;\/label&gt;\n                    &lt;source_model&gt;Magento\\Config\\Model\\Config\\Source\\Yesno&lt;\/source_model&gt;\n                &lt;\/field&gt;\n            &lt;\/group&gt;\n        &lt;\/section&gt;\n    &lt;\/system&gt;\n&lt;\/config&gt;<\/code><\/pre>\n\n\n\n<p>For simplicity:<\/p>\n\n\n\n<p>We will add the new <strong>Option Value GTIN <\/strong>tab to the config of our Advanced Product Options extension. You should be able to create a tab in your module too.<br><\/p>\n\n\n\n<p>The new <strong>Helper Class <\/strong>should be created. There, we will obtain data about the setting.<br><\/p>\n\n\n\n<p>So, let\u2019s create and fill in the following class:<br><\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/Helper\/Data.php`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\nnamespace VendorName\\OptionValueGtin\\Helper;\n\nuse Magento\\Framework\\App\\Helper\\AbstractHelper;\nuse Magento\\Store\\Model\\ScopeInterface;\nuse Magento\\Framework\\App\\Helper\\Context;\n\nclass Data extends AbstractHelper\n{\n\n    const XML_PATH_DEFAULT_OPTION_VALUE_GTIN  = 'mageworx_apo\/optionvaluegtin\/use_optionvaluegtin';\n\n    \/**\n     * Additional product attributes for product_attributes table\n     *\n     * @var array\n     *\/\n    protected $additionalProductAttributes;\n\n    \/**\n     * @param Context $context\n     *\/\n    public function __construct(\n        Context $context\n    ) {\n        parent::__construct($context);\n    }\n\n    \/**\n     * Check if option value GTIN enabled\n     *\n     * @param int|null $storeId\n     * @return string\n     *\/\n    public function isOptionValueGtinEnabled($storeId = null)\n    {\n        return $this-&gt;scopeConfig-&gt;getValue(\n            self::XML_PATH_DEFAULT_OPTION_VALUE_GTIN,\n            ScopeInterface::SCOPE_STORE,\n            $storeId\n        );\n    }\n\n}\n<\/code><\/pre>\n\n\n\n<p>Don\u2019t forget to save the changes and clear the cache.<br><\/p>\n\n\n\n<p>The setting should get displayed in the admin panel.<br><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/gFwuGQnVj2umIbguNKDLv-0MgINn3P_15UNZDVxSDaxspINZ9JykSh17p67daxt02H8_Q7EfUOnexuMCOqQ6vvvCBLZlU1r7iRMfCvwa7ADoi9OHRq0JTqs2aImW4UmUQlWZmfyK\" alt=\"How to add custom fields for products on Magento 2 | Mageworx Blog\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step #5. Displaying New Field on Product Page Front-End<\/h2>\n\n\n\n<p>Remember what we talked about in the <a href=\"https:\/\/www.mageworx.com\/blog\/how-to-add-custom-field-to-advanced-product-options-extension\/\">previous article<\/a>?<\/p>\n\n\n\n<p>We mentioned that our MageWorx_OptionBase module already has the `getExtendedOptionsConfig()` method that collects and displays all our custom attributes on the front-end via blocks.<br><\/p>\n\n\n\n<p>To see how it gets implemented, open the following class:<\/p>\n\n\n\n<p>`app\/code\/MageWorx\/OptionBase\/Block\/Product\/View\/Options.php`<br><\/p>\n\n\n\n<p>Now:<\/p>\n\n\n\n<p>Create a model with our attribute:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/Model\/Attribute\/OptionValue\/Gtin.php`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace VendorName\\OptionValueGtin\\Model\\Attribute\\OptionValue;\n\nuse MageWorx\\OptionBase\\Model\\Product\\Option\\AbstractAttribute;\n\nclass Gtin extends AbstractAttribute\n{\n    \/**\n     * @return string\n     *\/\n    public function getName()\n    {\n        return 'gtin';\n    }\n\n}\n<\/code><\/pre>\n\n\n\n<p>Via <strong>dependency injection<\/strong>, add the attribute to the general attributes block of the Advanced Product Options extension and create the following file:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/etc\/di.xml`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n&lt;config xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:ObjectManager\/etc\/config.xsd\"&gt;\n    &lt;!-- Data --&gt;\n    &lt;type name=\"MageWorx\\OptionBase\\Model\\Product\\Option\\Value\\Attributes\"&gt;\n        &lt;arguments&gt;\n            &lt;argument name=\"data\" xsi:type=\"array\"&gt;\n                &lt;item name=\"gtin\" xsi:type=\"object\"&gt;VendorName\\OptionValueGtin\\Model\\Attribute\\OptionValue\\Gtin&lt;\/item&gt;\n            &lt;\/argument&gt;\n        &lt;\/arguments&gt;\n    &lt;\/type&gt;\n&lt;\/config&gt;\n<\/code><\/pre>\n\n\n\n<p>Now:<br><\/p>\n\n\n\n<p>Create our new block and a template for it:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/Block\/ValueGtin.php`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace MageWorx\\OptionValueGtin\\Block;\n\nuse Magento\\Framework\\Json\\EncoderInterface;\nuse Magento\\Framework\\View\\Element\\Template;\nuse Magento\\Framework\\View\\Element\\Template\\Context;\nuse MageWorx\\OptionValueGtin\\Helper\\Data as Helper;\n\nclass ValueGtin extends Template\n{\n    \/**\n     * @var EncoderInterface\n     *\/\n    protected $jsonEncoder;\n\n    \/**\n     * @var Helper\n     *\/\n    protected $helper;\n\n    \/**\n     * @param Context $context\n     * @param EncoderInterface $jsonEncoder\n     * @param Helper $helper\n     * @param array $data\n     *\/\n    public function __construct(\n        Context $context,\n        EncoderInterface $jsonEncoder,\n        Helper $helper,\n        array $data = &#91;]\n    ) {\n        parent::__construct(\n            $context,\n            $data\n        );\n        $this-&gt;jsonEncoder = $jsonEncoder;\n        $this-&gt;helper = $helper;\n    }\n\n    \/**\n     * @return string\n     *\/\n    public function getJsonData()\n    {\n        $data = &#91;\n            'isOptionValueGtinEnabled' =&gt; $this-&gt;helper-&gt;isOptionValueGtinEnabled($this-&gt;_storeManager-&gt;getStore())\n        ];\n        return $this-&gt;jsonEncoder-&gt;encode($data);\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>Here, we\u2019ve obtained data about the setting from the <strong>Helper Class.<\/strong><br><\/p>\n\n\n\n<p>Next:<br><\/p>\n\n\n\n<p>Using the `getJsonData()` method, let\u2019s render data to the front-end using the template that we are about to create:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/view\/frontend\/templates\/config.phtml`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/** @var \\VendorName\\OptionValueGtin\\Block\\ValueGtin $block *\/\n?&gt;\n&lt;script&gt;\n    require(&#91;\n        'jquery',\n        'optionValueGtin',\n        'uiRegistry'\n    ], function ($, optionValueGtin, registry) {\n        var optionBase = registry.get('mageworxOptionBase');\n        if (optionBase) {\n            optionBase.addUpdater(7, optionValueGtin(&lt;?= \/* @noEscape *\/ $block-&gt;getJsonData() ?&gt;));\n        } else {\n            var updaters = registry.get('mageworxOptionUpdaters');\n            if (!updaters) {\n                updaters = {};\n            }\n            updaters&#91;7] = optionValueGtin(&lt;?= \/* @noEscape *\/ $block-&gt;getJsonData() ?&gt;);\n            registry.set('mageworxOptionUpdaters', updaters);\n        }\n    });\n&lt;\/script&gt;\n<\/code><\/pre>\n\n\n\n<p>We used the <strong>JavaScript mixins <\/strong>mechanism to display the values for the <strong>GTIN <\/strong>field.<br><\/p>\n\n\n\n<p>What\u2019s next?<br><\/p>\n\n\n\n<p>Let\u2019s take a different approach and create a js widget, which will be used to display the new data on the product page.<br><\/p>\n\n\n\n<p>Define the new js:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/view\/frontend\/requirejs-config.js`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var config = {\n    map: {\n        '*': {\n            optionValueGtin: 'VendorName_OptionValueGtin\/js\/option-value-gtin'\n        }\n    }\n};\n<\/code><\/pre>\n\n\n\n<p>It\u2019s high time to create the widget itself. It will contain all the logic in the work with the new attribute on the front-end.<br><\/p>\n\n\n\n<p>In the example file, let\u2019s implement the display logic of <strong>GTIN<\/strong> for the select options, and for the radio and check box options separately.<br><\/p>\n\n\n\n<p>&nbsp;These are going to be two different logics as the logic in the work and markup of such options differ from one another:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/view\/frontend\/web\/js\/option-value-gtin.js`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>define(&#91;\n    'jquery',\n    'Magento_Catalog\/js\/price-utils',\n    'underscore',\n    'jquery\/ui'\n], function ($, utils, _) {\n    'use strict';\n\n    $.widget('mageworx.optionValueGtin', {\n        options: {\n            optionConfig: {}\n        },\n\n        \/**\n         *\n         * @param optionConfig\n         * @param productConfig\n         * @param base\n         * @param self\n         *\/\n        firstRun: function firstRun(optionConfig, productConfig, base, self) {\n\n            if (parseFloat(this.options.isOptionValueGtinEnabled)) {\n                var extendedOptionsConfig = typeof base.options.extendedOptionsConfig != 'undefined' ?\n                    base.options.extendedOptionsConfig : {};\n\n                for (var option_id in optionConfig) {\n                    if (!optionConfig.hasOwnProperty(option_id)) {\n                        continue;\n                    }\n                    var $option = base.getOptionHtmlById(option_id);\n\n                    this._addValueGtin($option, optionConfig, extendedOptionsConfig);\n                }\n            }\n        },\n\n        \/**\n         * Add description to the values\n         * @param $option\n         * @param optionConfig\n         * @param extendedOptionsConfig\n         * @private\n         *\/\n        _addValueGtin: function _addValueGtin($option, optionConfig, extendedOptionsConfig) {\n            var self = this,\n                $options = $option.find('.product-custom-option');\n\n            \/\/selectable options\n            $options.filter('select').each(function (index, element) {\n                var $element = $(element),\n                    optionId = utils.findOptionId($element),\n                    value = extendedOptionsConfig&#91;optionId]&#91;'values'];\n\n                if ($element.attr('multiple') &amp;&amp; !$element.hasClass('mageworx-swatch')) {\n                    return;\n                }\n\n                if (typeof value == 'undefined' || _.isEmpty(value)) {\n                    return;\n                }\n\n                var gtinTitle = 'GTIN: ';\n                var $gtin = $('&lt;div class=\"option-value-gtin\"&gt;&lt;\/div&gt;', {\n                    style: 'display: none'\n                });\n\n                var $label = $option.find('.control');\n\n\n                $element.parent().prepend($gtin);\n                $element.on('change', function (e) {\n                    var valueId = $element.val();\n                    if (!_.isUndefined(value&#91;valueId]) &amp;&amp;\n                        !_.isEmpty(value&#91;valueId]&#91;'gtin'])\n                    ) {\n                        if ($label.length &gt; 0) {\n                            $label\n                                .first()\n                                .after($gtin.text(gtinTitle + value&#91;valueId]&#91;'gtin']));\n                        }\n                        $gtin.show();\n                    } else {\n                        $gtin.hide();\n                    }\n                });\n\n                if ($element.val()) {\n                    $element.trigger('change');\n                }\n            });\n\n            $options.filter('input&#91;type=\"radio\"], input&#91;type=\"checkbox\"]').each(function (index, element) {\n                var $element = $(element),\n                    optionId = utils.findOptionId($element),\n                    value = extendedOptionsConfig&#91;optionId]&#91;'values'];\n\n                if ($element.attr('multiple') &amp;&amp; !$element.hasClass('mageworx-swatch')) {\n                    return;\n                }\n\n                if (typeof value == 'undefined' || _.isEmpty(value)) {\n                    return;\n                }\n\n                var gtinTitle = 'GTIN: ';\n                var $gtin = $('&lt;div class=\"option-value-gtin-redio-check\"&gt;&lt;\/div&gt;');\n\n                var $label = $option.find('.control');\n\n\n                $element.parent().append($gtin);\n                var valueId = $element.val();\n                if (!_.isUndefined(value&#91;valueId]) &amp;&amp; !_.isEmpty(value&#91;valueId]&#91;'gtin'])) {\n                    $gtin.text(gtinTitle + value&#91;valueId]&#91;'gtin']);\n                }\n\n                if ($element.val()) {\n                    $element.trigger('change');\n                }\n            });\n        },\n    });\n\n    return $.mageworx.optionValueGtin;\n\n});\n<\/code><\/pre>\n\n\n\n<p>How about adding some styles?<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/view\/frontend\/web\/css\/valueGtin.css`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.option-value-gtin, .option-value-gtin-redio-check {\n    color: #1da0e0;\n    font-weight: 700;\n    margin-top: 5px;\n}\n\n.option-value-gtin-redio-check {\n    display: contents;\n}<\/code><\/pre>\n\n\n\n<p>It only remains to connect our block and the styles.<\/p>\n\n\n\n<p>For that, create the following file:<\/p>\n\n\n\n<p>`app\/code\/VendorName\/OptionValueGtin\/view\/frontend\/layout\/catalog_product_view.xml`<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n&lt;page layout=\"1column\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"urn:magento:framework:View\/Layout\/etc\/page_configuration.xsd\"&gt;\n    &lt;head&gt;\n        &lt;css src=\"VendorName_OptionValueGtin::css\/valueGtin.css\"\/&gt;\n    &lt;\/head&gt;\n    &lt;body&gt;\n        &lt;referenceBlock name=\"product.info.options.wrapper\"&gt;\n            &lt;container name=\"vendorname.option.value.gtin.container\" after=\"product.info.options\"&gt;\n                &lt;block class=\"VendorName\\OptionValueGtin\\Block\\ValueGtin\"\n                       name=\"vendorname.option.value.gtin\"\n                       template=\"VendorName_OptionValueGtin::config.phtml\"\/&gt;\n            &lt;\/container&gt;\n        &lt;\/referenceBlock&gt;\n    &lt;\/body&gt;\n&lt;\/page&gt;\n<\/code><\/pre>\n\n\n\n<p>We are almost finished.<br><\/p>\n\n\n\n<p>Before we run the final check, don\u2019t forget to clear the cache and deploy the static content again:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>php bin\/magento cache:flush<\/li><li>php bin\/magento static-content:deploy<\/li><\/ul>\n\n\n\n<p>And finally:<br><\/p>\n\n\n\n<p>Log in to the admin panel.<br><\/p>\n\n\n\n<p>Create a product with custom options in Magento product.<br><\/p>\n\n\n\n<p>In our example, I added dropdown, swatch, radio, and check box.<br><\/p>\n\n\n\n<p>Don\u2019t forget to fill in our new <strong>GTIN <\/strong>fields for the corresponding option values.<br><\/p>\n\n\n\n<p>Save the product.<br><\/p>\n\n\n\n<p>Time to see how it all looks like on the front-end:<br><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/Aer9eydZp-N8-85TLe1KW5Lw23qySmBOKIAvamQymEeJObeijS3XYTdOnu3HxFvEU9BZ3K7hDA95uoHNsIkCQKfKKIcTcuGqEu4NEaBi_I3r1ekIwuSOG5EwMnGE52lrM1fpN3Zl\" alt=\"How to add custom fields for products on Magento 2 | Mageworx Blog\"\/><\/figure>\n\n\n\n<p>What do you think about the result?<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Please share your feedback about the article in the comments field below. How easy was it to Magento add field to custom options?<\/p>\n\n\n<p><a href=\"https:\/\/calendly.com\/kate-volchock\/demo\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15060 size-full\" src=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2021\/02\/live-demo.png\" alt=\"Book a Live Demo with Mageworx\" width=\"690\" height=\"260\" srcset=\"https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2021\/02\/live-demo.png 690w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2021\/02\/live-demo-600x226.png 600w, https:\/\/www.mageworx.com\/blog\/wp-content\/uploads\/2021\/02\/live-demo-250x94.png 250w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/a><\/p>","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>From the previous article, you\u2019ve learned how to create Magento custom option fields. We also have found out how to display the field data on both the product page front-end and the order page in the admin panel. What\u2019s now? Let\u2019s learn how to add the same custom GTIN field for the option values and [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":12872,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[255,425],"tags":[379,436],"class_list":{"0":"post-12868","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-apo","10":"tag-developer-diaries"},"_links":{"self":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/12868","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\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/comments?post=12868"}],"version-history":[{"count":12,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/12868\/revisions"}],"predecessor-version":[{"id":15071,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/posts\/12868\/revisions\/15071"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media\/12872"}],"wp:attachment":[{"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/media?parent=12868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/categories?post=12868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mageworx.com\/blog\/wp-json\/wp\/v2\/tags?post=12868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}