6

I'd like to create my custom field type to use it in system config forms (System -> Configuration). For example, to create simple text field we need to use <frontend_type>text</frontend_type> in system.xml which tells Magento to use file lib/Varien/Data/Form/Element/Text.php:

<config>
    <!-- ... -->
    <sections>
        <mycustom_section translate="label">
            <label>My Module</label>
            <sort_order>0</sort_order>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>1</show_in_store>
            <groups>
                <mycustom_group translate="label">
                    <label>My Custom Group</label>
                    <sort_order>0</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <heading_sample translate="label">
                            <label>Sample heading</label>
                            <sort_order>0</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
                        </heading_sample>
                        <mycustom_field translate="label comment">
                            <label>My Custom Field</label>
                            <sort_order>1</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <frontend_type>text</frontend_type> <!-- custom field type here -->
                            <frontend_model>mymodule/custom</frontend_model> <!-- or custom model here -->
                        </mycustom_field>
                        <!-- ...other fields here... -->
                    </fields>
                </mycustom_group>
            </groups>
        </mycustom_section>
    </sections>
</config>

If I create my own class (that extends Magento's Varien_Data_Form_Element_Abstract class) that renders my custom field, where I should put this file?

It will probably work (will it?) if I put it inside Magento default directory lib/Varien/Data/Form/Element/Customized.php:

<mycustom_group>
<!-- ... -->
    <fields>
        <mycustom_field translate="label comment">
            <label>My Custom Field</label>
            <comment>Some comment about my field</comment>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>1</show_in_store>
            <frontend_type>customized</frontend_type>  <!-- custom field type here -->
        </mycustom_field>
    </fields>
</mycustom_group>
  1. But is there any way to keep my custom field file inside my custom module instead in lib/Varien/Data/Form/Element/? Adding custom files to the core directories isn't probably very good idea.

  2. If not, can I create custom folder inside lib/, for example: lib/Mycompany/Customized.php? But in that case, how I can inform Magento in the <frontend_type> tag inside system.xml that it should use my custom field file and tell Magento where that file is located?

4
  • which type of System Configuration you have to make ?
    – Keyul Shah
    May 29, 2014 at 0:58
  • @KeyulShah I'm adding custom options for my module in System -> Configuration -> My Module. I will add simple text fields, simple drop-down lists but also I need to add there some custom extended fields for which Magento doesn't have any default form fields (so I need to build my own).
    – kahirm
    May 29, 2014 at 10:08
  • Did you try to use the magento syntax? yourcompany/customized for the frontend_type? May 29, 2014 at 10:28
  • @FabianBlechschmidt If I use <frontend_type>yourcompany/customized</frontend_type> in system.xml, then where I should put my file? This is the part which I don't understand. :)
    – kahirm
    May 29, 2014 at 10:34

2 Answers 2

6

So the easy but not recommended way is to put your element under app/code/local/Varien/Data/Form/Element/. As Magento is simply using the order of include_paths and will first look into the local folder, before it goes to the lib folder.

But the wiring to Varien_Data_Form_Element is just a fallback which is defined in lib\Varien\Data\Form\Abstract.php.

public function addField($elementId, $type, $config, $after=false)
{
    if (isset($this->_types[$type])) {
        $className = $this->_types[$type];
    }
    else {
        $className = 'Varien_Data_Form_Element_'.ucfirst(strtolower($type));
    }

So the question is where can you defined that _types array? There is an addType method in the same class which can be called. When you search for that method you might stumble over an iteration of _getAdditionalElementTypes on the form block in app\code\core\Mage\Adminhtml\Block\Widget\Form.php

protected function _addElementTypes(Varien_Data_Form_Abstract $baseElement)
{
    $types = $this->_getAdditionalElementTypes();
    foreach ($types as $code => $className) {
        $baseElement->addType($code, $className);
    }
}

The default implementation of _getAdditionalElementTypes just returns an empty array, but there is already some working implementation in the Magento Core in Mage_Adminhtml_Block_Sales_Order_Create_Form_Abstract.

So that example looks like:

protected function _getAdditionalFormElementTypes()
{
    return array(
        'file'      => Mage::getConfig()->getBlockClassName('adminhtml/customer_form_element_file'),
        'image'     => Mage::getConfig()->getBlockClassName('adminhtml/customer_form_element_image'),
        'boolean'   => Mage::getConfig()->getBlockClassName('adminhtml/customer_form_element_boolean'),
    );
}

And even in your form which you need to extend: Mage_Adminhtml_Block_System_Config_Form

protected function _getAdditionalElementTypes()
{
    return array(
        'export'        => Mage::getConfig()->getBlockClassName('adminhtml/system_config_form_field_export'),
        'import'        => Mage::getConfig()->getBlockClassName('adminhtml/system_config_form_field_import'),
        'allowspecific' => Mage::getConfig()
            ->getBlockClassName('adminhtml/system_config_form_field_select_allowspecific'),
        'image'         => Mage::getConfig()->getBlockClassName('adminhtml/system_config_form_field_image'),
        'file'          => Mage::getConfig()->getBlockClassName('adminhtml/system_config_form_field_file')
    );
}

Based on that you should be able to implement your own _getAdditonalFormElementTypes by rewriting the System_Config_Form which can then handle new frontend types in your config.

€: Thinking about the question of Fabian it should also be possible by using an observer. The addType method on the form element is public, so you can call that and add custom types from and observer. You need to listen to an event in the form object and in the observer add your custom types. Just make sure this happens before _initFields, which is called from initForm. So a good point can be the prepare_layout events which are called before the initForm method (see Mage_Adminhtml_Block_System_Config_Edit->initForm and Mage_Core_Block_Abstract->setLayout)

8
  • 2
    If I understand you correct, there is no simple way via adding an action to the layout.xml or calling something in an observer to do this!? :-( This is sad. May 29, 2014 at 11:00
  • 1
    Not that I know, but I'm willing to learn if someone knows a better way ;)
    – Tobias
    May 29, 2014 at 11:01
  • @TobiasZander Forgive me my ignorance, but I'm still not sure how i should implement it. Could you extend tour example a little bit and show how to implement this to creat custom field type? Of course omit the details of the field HTML etc. as this is not important right now (I know I need to extend Varien_Data_Form_Element_Abstract).
    – kahirm
    May 29, 2014 at 11:31
  • 1
    As you want to extend the system/configuration form you'll have to rewrite the Mage_Adminhtml_Block_System_Config_Form class. Check the _getAdditionalElementTypes method there and overwrite it with your custom elements
    – Tobias
    May 29, 2014 at 12:26
  • 2
    @TobiasZander I edited my example. What if I create custom block and use it in <frontend_model> tag in system.xml? The block can extend Mage_Adminhtml_Block_System_Config_Form_Field similar to block Mage_Adminhtml_Block_System_Config_Form_Field_Heading which Magento use to create headings in the system config. Maybe inside that block there is some way to call that addType method to add custom type of the field?
    – kahirm
    May 29, 2014 at 16:04
2

I don't agree with above solution, you should not rewrite the System_Config_Form because if everybody follow a similar approach you will have a mess (aka: a lot of conflicts between modules).

A better practice is to use the xml tag <frontend_model> in your system.xml config file.

The following example cover the scenario where you want a full custom field otherwise the are

BLOCK FILE

<?php

class COMPANY_MODULE_Block_Adminhtml_System_Myfield extends Mage_Adminhtml_Block_Abstract
    implements Varien_Data_Form_Element_Renderer_Interface
{
    // this will look in adminhtml theme
    protected $_template = 'my/template/myfield.phtml'; 

    public function render(Varien_Data_Form_Element_Abstract $element)
    {
        return $this->toHtml();
    }
}

TEMPLATE FILE
Just put whatever html you want here

XML FILE ( the only thing special here is the <frontend_model> tag

<?xml version="1.0"?>
<config>
    <sections>
        <MYMODULE translate="label" module="translator">
            <groups>
                <general>
                    <label>GROUP TITLE</label>
                    <sort_order>999</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <my_custom_field translate="label">
                            <frontend_model>MODULE/adminhtml_system_myfield</frontend_model>
                            <sort_order>40</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </my_custom_field>
                    </fields>
                </general>    
            </groups>
        </MYMODULE>
    </sections>
</config>

NOTE
If you need to save some values you will have to deal with the <backend_model> tag
Here some info: http://alanstorm.com/magento_system_config_validation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.