Dynamic show/hide data fields in Magento
- Oleksandr Drok
- Uncategorized
- Feb 19, 2015
- 2 min read
Let's create two text control elements in HTML form:
$element = $fieldset->addField('one', 'text', array( 'label' => Mage::helper('helpdesk')->__('Carbon Copy'), 'name' => 'one', 'value' => '', 'required' => false, )); $element = $fieldset->addField('two', 'text', array( 'label' => Mage::helper('helpdesk')->__('Blind Carbon Copy'), 'name' => 'two', 'value' => '', 'required' => false ));
To create dependency between these fields, we need to add a new hidden block with special controller of one field’s value and the other’s visibility to the form. As such, you need to employ the override method toHtml() and add to the layout block of adminhtml/widget_form_element_dependence type. There, we can create two field maps, which must contain field IDs, their respective names (it’s better to have them match), and the dependency, itself.
protected function _toHtml() { $dependency_block = $this->getLayout() ->createBlock('adminhtml/widget_form_element_dependence') ->addFieldMap('one', 'one') ->addFieldMap('two', 'two') ->addFieldDependence('one', 'two', 'true'); return parent::_toHtml() . $dependency_block->toHtml(); }
Now, if we enter “true” in the field one and jump to the other control element (so our element loses focus and the event onChange is generated), we will have a field two that is visible. If we clear or enter other text into one field, the two will disappear again.
The problem becomes more complex if visibility must depend on a button, anchor or reference. In this case, we need an additional trigger field of type hidden. But setting value of that field, by script, will not dispatch onChange event, so we need to fire it manually.
Let’s create a reference, hidden control and text field.
$fieldset->addField('hiddenCtrl', 'hidden', array('name'=>'hiddenCtrl', 'value' => 'false')); $element = $fieldset->addField('invisibleCtrl', 'text', array( 'label' => Mage::helper('helpdesk')->__('Invisible'), 'name' => 'invisibleCtrl', 'value' => '', 'required' => false, ));
Visibility controller is the same and in the same place, with setting dependency between the hidden and text fields.
$dependency_block = $this->getLayout() ->createBlock('adminhtml/widget_form_element_dependence') ->addFieldMap('hiddenCtrl', 'hiddenCtrl') ->addFieldMap('invisibleCtrl', 'invisibleCtrl') ->addFieldDependence('invisibleCtrl', 'hiddenCtrl', 'true') ;
We also need a script to run the onclick reference, switch values of hidden field and manually generate an event. It will have one argument – identifier of the hidden field, where values are to be switched.
(*not sure I understood this, or changed the meaning by editing it*)function switchVisible(controlId) { // Switch values if(document.getElementById(controlId).value == 'true') { document.getElementById(controlId).value = 'false'; } else { document.getElementById(controlId).value = 'true'; } // Emulate event if(document.createEventObject) { var evt = document.createEventObject(); document.getElementById(controlId).fireEvent('onchange', evt); } else { var evt = document.createEvent('HTMLEvents'); evt.initEvent('change', false, true); document.getElementById(controlId).dispatchEvent(evt); } }
Done.
A compatibility note: while the document.getElementById method is a standard DOM function that is only not supported by ancient browsers like Netscape Navigator, event generation slightly differs in Internet Explorer, Mozilla and Chrome, meaning that the task we implemented employs a two-branch condition with simple detection of the browser model. If the document.createEventObject method exists, then the browser uses IE’s DOM model; in the other case – the model is Mozilla/Chrome.