Adding a Custom Form Element to an Adminhtml Form
Is there a way to add a custom form element to a Magento Adminhtml form without placing the custom element in the lib/Varian
folder?
I've tracked down the code that's essentially a Varian_Data_Form_Element_
factory
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));
}
$element = new $className($config);
$element->setId($elementId);
if ($element->getRequired()) {
$element->addClass('required-entry');
}
$this-&开发者_Python百科gt;addElement($element, $after);
return $element;
}
So, if I'm reading this correctly, I ensure that an EAV attribute's frontend returns a specific fieldType, (such as supertextfield
) and the system will instantiate/render a Varien_Data_Form_Element_Supertextfield
when displaying this attribute's editing form.
This is well and good, but it means I need to include my custom form element in the lib/Varian
folder hierarchy. Given how module oriented Magento is, it seems like this is doing it wrong.
I realize I could jank around with a custo autoloader or symlinks in the lib, but I'm primarily interested in learning if there's
A canonical way to add custom form elements for attributes
A canonical way to customize the Magento autoloader.
This is an old post but it still can be usefull for someone :
yes you can.
The code below is located in : app/code/local/MyCompany/MyModule/Block/MyForm.php
class MyCompany_MyModule_Block_MyForm extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save'),
'method' => 'post'
));
$fieldset = $form->addFieldset('my_fieldset', array('legend' => 'Your fieldset title')));
//Here is what is interesting us
//We add a new type, our type, to the fieldset
//We call it extended_label
$fieldset->addType('extended_label','MyCompany_MyModule_Lib_Varien_Data_Form_Element_ExtendedLabel');
$fieldset->addField('mycustom_element', 'extended_label', array(
'label' => 'My Custom Element Label',
'name' => 'mycustom_element',
'required' => false,
'value' => $this->getLastEventLabel($lastEvent),
'bold' => true,
'label_style' => 'font-weight: bold;color:red;',
));
}
}
Here is the code of your custom element, which is located in app/code/local/MyCompany/MyModule/Lib/Varien/Data/Form/Element/ExtendedLabel.php :
class MyCompany_MyModule_Lib_Varien_Data_Form_Element_ExtendedLabel extends Varien_Data_Form_Element_Abstract
{
public function __construct($attributes=array())
{
parent::__construct($attributes);
$this->setType('label');
}
public function getElementHtml()
{
$html = $this->getBold() ? '<strong>' : '';
$html.= $this->getEscapedValue();
$html.= $this->getBold() ? '</strong>' : '';
$html.= $this->getAfterElementHtml();
return $html;
}
public function getLabelHtml($idSuffix = ''){
if (!is_null($this->getLabel())) {
$html = '<label for="'.$this->getHtmlId() . $idSuffix . '" style="'.$this->getLabelStyle().'">'.$this->getLabel()
. ( $this->getRequired() ? ' <span class="required">*</span>' : '' ).'</label>'."\n";
}
else {
$html = '';
}
return $html;
}
}
The class Varien_Data_Form_Abstract
has a method addType()
where you can add new element types and their respective class names. To exploit this functionality you can copy the block Mage_Adminhtml_Block_Widget_Form
to the local code pool and extend the method _getAdditionalElementTypes()
:
protected function _getAdditionalElementTypes()
{
$types = array(
'my_type' => 'Namespace_MyModule_Block_Widget_Form_Element_MyType',
);
return $types;
}
As the class Mage_Adminhtml_Block_Widget_Form
is a base class for all the other form classes, unfortunately just rewriting the block in the config will not work.
EDIT: If you need the custom element types in just one form you could override the specific class and add the type there by overriding the method _getAdditionelElementTypes()
. This would be a cleaner solution than copying an importend magento class to the local code pool.
EDIT2: Looking at Mage_Adminhtml_Block_Widget_Form::_setFieldset()
there is another possibility: If the attribute has a value in frontend_input_renderer
(e.g. mymodule/element_mytype) then a block with that name is loaded. See also Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php line 160. This should work without overriding any Magento classes.
Self help desk strikes again. It looks like Magento sets up include paths in such a way that you can drop class files from lib (not just from the Mage_ namespace) in your local code branch
app/code/local/Varien/etc
When the autoloader tries to load a lib/Varien class, it will check your directory first. This still puts you at risk if Varien ever creates a data element with the same name as yours, but as risks go it's relatively low.
精彩评论