We’ve had a couple of projects lately where we had to do some fancy system configuration and found some cool tricks by extending Mage_Adminhtml_Block_System_Config_Form_Field.
One sets up the system module configuration by adding a system.xml file to the module etc/ folder. This xml file will have a node for each configuration setting (i.e. field) you need to save for your module. This works really well if you just need to save a simple text value but if you want to do something fancier you can also set your own class as the ‘frontend_model’ of the field. This ‘frontend_model’ handles displaying the field in the admin interface and should extend Mage_Adminhtml_Block_System_Config_Form_Field.
Our first trick came up because we wanted to store a serialized array of values for a particular field instead of just a simple text value. We did this by overriding the ‘render’ function to unserialze the array and format the data in our custom fieldset, ready to be saved by Magento upon submit (we used an observer listening to ‘admin_system_config_changed_section_<system>’ to process the data and save the serialized array. Perhaps there are cleaner approaches). The markup one needs to generate and can get pretty burly. You’ll need to sort out the configuration inheritence but it’s straightforward, in principle, take a look at the function you’re overriding you can see how this stuff has to work.
Our second trick came up because we wanted to have an AJAX button on the system configuration form as opposed to a field to save. We could have overridden the ‘render’ function again but there was enough markup being returned that we decided to use a template file instead. We did this by overriding ‘_prepareLayout’ to set a template for the field block, then we overwrote ‘_getElementHtml’ to return $this->_toHtml() as opposed to $element->getElementHtml(). Then when the default ‘render’ function executes it inserts our template markup where the element markup was supposed to go. I wonder if we could have done a cleaner job by extending the element itself instead of the field but that will have to wait for another blogpost.