Magento 2 - How to Add Custom Input Type in Custom Option

Some time we needs to add custom input type in Magento 2 customizable option for fulfilling our client's requirements which is not covered with the default custom option type. So, in this article, We are going to explain some simple steps to add a custom options custom input type in Magento 2.

Before we start I assume, you have already a created custom module. If you don't have it or don't know how to create it then check out our other article How To Create a Magento 2 Module.

Let's add new input type in option type dropdown in Magento 2 customizable option

Please follow bellow simple steps to Add Custom Field in Custom Option.

Step 1. Create registration.php file at Vendor/Module/registration.php and paste the below code.

Copy
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_Module',
    __DIR__
);

Step 2. Create module.xml file at Vendor/Module/etc/module.xml and paste the below code.

Copy
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="1.0.0">
		<sequence>
			<module name="Magento_Catalog"/>
		</sequence>
    </module>
</config>

Step 3. Create product_options.xml file at Vendor/Module/etc/product_options.xml and paste the below code.

Copy
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/product_options.xsd">
    <option name="text" label="Text" renderer="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options\Type\Text">
        <inputType name="field" label="Field"/>
        <inputType name="area" label="Area"/>
    </option>
    <option name="file" label="File" renderer="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options\Type\File">
        <inputType name="file" label="File"/>
    </option>
    <option name="select" label="Select" renderer="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options\Type\Select">
        <inputType name="drop_down" label="Drop-down"/>
        <inputType name="radio" label="Radio Buttons"/>
        <inputType name="checkbox" label="Checkbox"/>
        <inputType name="multiple" label="Multiple Select"/>
        <inputType name="new_option_type" label="New Option Type"/>
    </option>
    <option name="date" label="Date" renderer="Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options\Type\Date">
        <inputType name="date" label="Date"/>
        <inputType name="date_time" label="Date &amp; Time"/>
        <inputType name="time" label="Time"/>
    </option>
</config>

Step 4. Create di.xml file at Vendor/Module/etc/di.xml and paste the below code.

Copy
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<preference for="Magento\Catalog\Block\Product\View\Options\Type\Select" type="Vendor\Module\Block\Product\View\Options\Type\Select" />
    <preference for="Magento\Catalog\Model\Product\Option" type="Vendor\Module\Model\Product\Option" />
</config>

Step 5. Create Select.php file at Vendor/Module/Block/Product/View/Options/Type/Select.php and paste the below code.

Copy
<?php

namespace Vendor\Module\Block\Product\View\Options\Type;

use Magento\Catalog\Block\Product\View\Options\Type\Select\CheckableFactory;
use Magento\Catalog\Block\Product\View\Options\Type\Select\MultipleFactory;
use Magento\Catalog\Helper\Data as CatalogHelper;
use Magento\Catalog\Model\Product\Option;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Pricing\Helper\Data;
use Magento\Framework\View\Element\Template\Context;
use Vendor\Module\Model\Product\Option as ProductModel;

class Select extends \Magento\Catalog\Block\Product\View\Options\AbstractOptions
{
    private $checkableFactory;
    private $multipleFactory;

    public function __construct(
        Context $context,
        Data $pricingHelper,
        CatalogHelper $catalogData,
        array $data = [],
        CheckableFactory $checkableFactory = null,
        MultipleFactory $multipleFactory = null
    ) {
        parent::__construct($context, $pricingHelper, $catalogData, $data);
        $this->checkableFactory = $checkableFactory ?: ObjectManager::getInstance()->get(CheckableFactory::class);
        $this->multipleFactory = $multipleFactory ?: ObjectManager::getInstance()->get(MultipleFactory::class);
    }

    public function getValuesHtml(): string
    {
        $option = $this->getOption();
        $optionType = $option->getType();
        if ($optionType === Option::OPTION_TYPE_DROP_DOWN ||
            $optionType === Option::OPTION_TYPE_MULTIPLE ||
            $optionType === ProductModel::OPTION_TYPE_NEW_OPTION_TYPE
        ) {
            $optionBlock = $this->multipleFactory->create();
        }
        if ($optionType === Option::OPTION_TYPE_RADIO ||
            $optionType === Option::OPTION_TYPE_CHECKBOX
        ) {
            $optionBlock = $this->checkableFactory->create();
        }
        return $optionBlock
            ->setOption($option)
            ->setProduct($this->getProduct())
            ->setSkipJsReloadPrice(1)
            ->_toHtml();
    }
}

Step 6. Create Option.php file at Vendor/Module/Model/Product/Option.php and paste the below code.

Copy
<?php

namespace Vendor\Module\Model\Product;

use Magento\Catalog\Model\Product;

class Option extends \Magento\Catalog\Model\Product\Option
{
    const OPTION_TYPE_NEW_OPTION_TYPE = 'new_option_type';

    private $optionTypesToGroups;

    public function getGroupByType($type = null)
    {
        if ($type === null) {
            $type = $this->getType();
        }
        $optionTypesToGroups = [
            self::OPTION_TYPE_FIELD => self::OPTION_GROUP_TEXT,
            self::OPTION_TYPE_AREA => self::OPTION_GROUP_TEXT,
            self::OPTION_TYPE_FILE => self::OPTION_GROUP_FILE,
            self::OPTION_TYPE_DROP_DOWN => self::OPTION_GROUP_SELECT,
            self::OPTION_TYPE_RADIO => self::OPTION_GROUP_SELECT,
            self::OPTION_TYPE_CHECKBOX => self::OPTION_GROUP_SELECT,
            self::OPTION_TYPE_MULTIPLE => self::OPTION_GROUP_SELECT,
            self::OPTION_TYPE_NEW_OPTION_TYPE => self::OPTION_GROUP_SELECT,
            self::OPTION_TYPE_DATE => self::OPTION_GROUP_DATE,
            self::OPTION_TYPE_DATE_TIME => self::OPTION_GROUP_DATE,
            self::OPTION_TYPE_TIME => self::OPTION_GROUP_DATE,
        ];
        return isset($optionTypesToGroups[$type]) ? $optionTypesToGroups[$type] : '';
    }
}

Step 7. Create di.xml file at Vendor/Module/adminhtml/di.xml and paste the below code.

Copy
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<virtualType name="Magento\CatalogStaging\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
		<arguments>
			<argument name="modifiers" xsi:type="array">
				<item name="new-modifier-all" xsi:type="array">
					<item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\All</item>
					<item name="sortOrder" xsi:type="number">71</item>
				</item>
			</argument>
		</arguments>
	</virtualType>
	<virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
		<arguments>
			<argument name="modifiers" xsi:type="array">
				<item name="new-modifier-all" xsi:type="array">
					<item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\All</item>
					<item name="sortOrder" xsi:type="number">71</item>
				</item>
			</argument>
		</arguments>
	</virtualType>
	<virtualType name="Vendor\Module\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
		<arguments>
			<argument name="modifiers" xsi:type="array">
			</argument>
		</arguments>
	</virtualType>
	<type name="Vendor\Module\Ui\DataProvider\Product\Form\Modifier\All">
		<arguments>
			<argument name="pool" xsi:type="object">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\Pool</argument>
		</arguments>
	</type>
	<virtualType name="Vendor\Module\Ui\DataProvider\Product\Form\Modifier\Pool">
		<arguments>
			<argument name="modifiers" xsi:type="array">
				<item name="new-custom-option" xsi:type="array">
					<item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\CustomOptions</item>
					<item name="sortOrder" xsi:type="number">72</item>
				</item>
			</argument>
		</arguments>
	</virtualType>
</config>

Step 8. Create All.php file at Vendor/Module/Ui/DataProvider/Product/Form/Modifier/All.php and paste the below code.

Copy
<?php

namespace Vendor\Module\Ui\DataProvider\Product\Form\Modifier;

use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
use Magento\Ui\DataProvider\Modifier\ModifierInterface;
use Magento\Ui\DataProvider\Modifier\PoolInterface;

class All extends AbstractModifier implements ModifierInterface
{
    protected $pool;
    protected $meta = [];

    public function __construct(
        PoolInterface $pool
    ) {
        $this->pool = $pool;
    }

    public function modifyData(array $data)
    {
        foreach ($this->pool->getModifiersInstances() as $modifier) {
            $data = $modifier->modifyData($data);
        }

        return $data;
    }

    public function modifyMeta(array $meta)
    {
        $this->meta = $meta;

        foreach ($this->pool->getModifiersInstances() as $modifier) {
            $this->meta = $modifier->modifyMeta($this->meta);
        }

        return $this->meta;
    }
}

Step 9. Create CustomOptions.php file at Vendor/Module/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php and paste the below code.

Copy
<?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 as CustomOptionsModifier;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\StoreManagerInterface;

class CustomOptions extends AbstractModifier
{
    protected $meta = [];

    public function __construct(
        UrlInterface $urlBuilder,
        LocatorInterface $locator,
        StoreManagerInterface $storeManager
    ) {
        $this->urlBuilder = $urlBuilder;
        $this->locator = $locator;
        $this->storeManager = $storeManager;
    }

    public function modifyData(array $data)
    {
        return $data;
    }

    public function modifyMeta(array $meta)
    {
        $this->meta = $meta;

        $this->addCustomOptionsFields();

        return $this->meta;
    }

    protected function addCustomOptionsFields()
    {
        $groupCustomOptionsName = CustomOptionsModifier::GROUP_CUSTOM_OPTIONS_NAME;
        $optionContainerName = CustomOptionsModifier::CONTAINER_OPTION;
        $commonOptionContainerName = CustomOptionsModifier::CONTAINER_COMMON_NAME;
        $fieldTypeName = CustomOptionsModifier::FIELD_TYPE_NAME;

        // Add new option type to select
        $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
        [$optionContainerName]['children']
        [$commonOptionContainerName]['children']
        [$fieldTypeName]['arguments']['data']['config']['groupsConfig']['select'] = $this->getSelect();
    }

    private function getSelect()
    {
        return [
            'values' => [
                'drop_down',
                'radio',
                'checkbox',
                'multiple',
                'new_option_type',
            ],
            'indexes' => [
                CustomOptionsModifier::GRID_TYPE_SELECT_NAME,
            ],
        ];
    }
}

Step 10. Now install Module using the below commands

If your magento is running in a production mode then change it to developer mode before install this module.

Copy
php bin/magento deploy:mode:set developer
php bin/magento s:up
php bin/magento s:s:d -f
php bin/magento c:c

If you are a beginner and want to know more about Magento 2 Commands then check out our other article which is Useful Commands for Magento 2.

Now add new or edit any product from admin panel and check new custom option input type New Option Type is added in option type dropdown.

That’s it!

If you are looking for a solution to Add Custom Field in Custom Option values then please check our another article which is Magento 2 How to Add Custom Field in Custom Option Value

We also have a solution to Add Custom Field in Custom Option, please check How to Add Custom Field in Custom Option

I hope this Magento article helped you to find what you were looking for.

Bookmark it for your future reference. Do comment below if you have any other handy commands which are not included in the list.

P.S. Do share this note with your team.




Search
Recent Posts
    Tags
    Newsletter
    SocialFollow on Twitter
    Visit now!