Magento – Create custom “Catalog Input Type for Store Owner” for magento 2

adminhtmlmagento2moduleproduct-attribute

I need to create a special input type in adminhtml product form. My input will display as a table but save data as a standard text input.

Following the module Edge ProductAttachments I've created the module for magento 1.

Now a I'm trying to convert the module for magento 2, but when create a new product I obtain the error Class inputtable does not exist.

The steps to reproduce the error on an empty magento 2.0.2 installation:

  • Stores -> Product-> Add New Attribute
  • Set Catalog Input Type for Store Owner to Inputtable and Default label to Mytable
  • Click Save Attribute
  • Add the new attribute to Default attribute set
  • Product -> Catalog -> Add Product (simple product)

This is my code:

File: Fun/Tablegrid/etc/module.xml

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

File: Fun/Tablegrid/etc/config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <general>
            <validator_data>
                <input_types>
                    <tableinput>tableinput</tableinput>
                </input_types>
            </validator_data>           
        </general>
    </default>
</config>

File: Fun/Tablegrid/etc/adminhtml/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="adminhtml_product_attribute_types">
        <observer name="tablegrid" instance="Fun\Tablegrid\Observer\AddTableinputAttributeTypeObserver" />
    </event>
</config>

File: Fun/Tablegrid/Block/Attribute/Renderer.php

<?php
namespace Fun\Tablegrid\Block\Attribute;
use \Magento\Framework\Currency;

class Renderer extends \Magento\Framework\Data\Form\Element\Text
{
    public function getHtml()
    {
        $this->addClass('input-table');
        return parent::getHtml();
    }
    //remove the other code to compact question 
}

File: Fun/Tablegrid/Model/Catalog/ResourceModel/Attribute.php

<?php
namespace Fun\Tablegrid\Model\Catalog\ResourceModel;

class Attribute extends \Magento\Catalog\Model\ResourceModel\Attribute
{
    protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object){
        if ($object->getFrontendInput() === 'tableinput'){
            $object->setBackendType('text');
            $object->setFrontendInputRenderer('tablegrid/attribute_renderer');
        }
        return parent::_beforeSave($object);
    }
}

File: Fun/Tablegrid/Observer/AddTableinputAttributeTypeObserver.php

<?php
namespace Fun\Tablegrid\Observer;
use Magento\Framework\Event\ObserverInterface;

class AddTableinputAttributeTypeObserver implements ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer){
        $response = $observer->getEvent()->getResponse();
        $types = $response->getTypes();
        $types[] = [
            'value' => 'tableinput',
            'label' => __('Tableinput'),
        ];
        $response->setTypes($types);
        return $this;
    }
}

Best Answer

In Fun/Tablegrid/Model/Catalog/ResourceModel/Attribute.php, try:

protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object){
    if ($object->getFrontendInput() === 'tableinput'){
        $object->setBackendType('text');
        /* Use setData() and specify full class name below */
        $object->setData('frontend_input_renderer', 'Endertech\Numeric\Block\Adminhtml\Attribute\Numeric');
    }
    return parent::_beforeSave($object);
}