In http://alanstorm.com/magento_system_configuration_in_depth_tutorial @AlanStorm gives a very good tutorial for system con开发者_JAVA百科figuration.
He also explains how to use a <depends> tag to make a field show only when a specific value is set in another field.
My Q is how can I make fieldB visible if field A has either value V1 or V2. and are there any other options with the <depends> ?
Also If someone knows where in magento's code this is implemented I would also like to have a look at the code myself.
Thanks
If I correctly understand release notes from Magento 1.7.0.1, this functionnality has been implemented (http://goo.gl/ZgHG0). I have succeddfully tested it on a Magento CE 1.7.0.2.
You must declare a separator parameter in the field dependancy like this :
<depends>
<depends_from_field separator=",">
depends_from_field_value_1,depends_from_field_value_2
</depends_from_field>
</depends>
Note that depends_from_field_value_1
and depends_from_field_value_2
are separated by a comma, the exact symbol that is declared in separator=","
There is a better way, but you will need to override the core files
Override the method under the following file app\code\core\Mage\Adminhtml\Block\Widget\Form\Element\Dependence.php
public function addFieldDependence($fieldName, $fieldNameFrom, $refValues)
{
/*
if (is_array($refValues)) {
Mage::throwException('Dependency from multiple values is not implemented yet. Please fix to your widget.xml');
}
*/
$this->_depends[$fieldName][$fieldNameFrom] = $refValues;
return $this;
}
On the app\code\core\Mage\Adminhtml\Block\System\Config\Form.php Modify the method initFields
if ($e->depends) {
foreach ($e->depends->children() as $dependent) {
$dependentId = $section->getName() . '_' . $group->getName() . '_' . $fieldPrefix . $dependent->getName();
if ($dependent->count()) {
$dependentValue = (array) $dependent;
$dependentValue = array_values($dependentValue);
} else {
$dependentValue = (string) $dependent;
}
$this->_getDependence()
->addFieldMap($id, $id)
->addFieldMap($dependentId, $dependentId)
->addFieldDependence($id, $dependentId, $dependentValue);
}
}
Modify the javascript file js\mage\adminhtml\form.js
trackChange : function(e, idTo, valuesFrom)
{
// define whether the target should show up
var shouldShowUp = true;
for (var idFrom in valuesFrom) {
if (valuesFrom.hasOwnProperty(idFrom)) {
if (typeof(valuesFrom[idFrom])=="object") {
shouldShowUp = false;
for(var idVal in valuesFrom[idFrom]) {
if (valuesFrom[idFrom].hasOwnProperty(idVal)) {
if (typeof(idVal)!="undefined" && ($(idFrom).value == valuesFrom[idFrom][idVal])) {
shouldShowUp = true;
}
}
}
} else if (typeof(valuesFrom[idFrom])=="string") {
if ($(idFrom).value != valuesFrom[idFrom]) {
shouldShowUp = false;
}
}
}
/*
if ($(idFrom).value != valuesFrom[idFrom]) {
shouldShowUp = false;
}
*/
}
// toggle target row
if (shouldShowUp) {
$(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item) {
if (!item.type || item.type != 'hidden') { // don't touch hidden inputs, bc they may have custom logic
item.disabled = false;
}
});
$(idTo).up(this._config.levels_up).show();
} else {
$(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item){
if (!item.type || item.type != 'hidden') { // don't touch hidden inputs, bc they may have custom logic
item.disabled = true;
}
});
$(idTo).up(this._config.levels_up).hide();
}
}
Use the following syntax for multiple values dependency on your xml
<depends>
<field1>
<val1>text</val1>
<val2>radio</val2>
</field1>
</depends>
I'm not sure where in Alan's article it's explained, but there is how I do it: it's just a bit of javascript.
In your group you put a comment tag with the javascript embedded into .
For example, here is my code that checks the value of one field in order to show (or not) another one:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<sections>
<points_options translate="label" module="points">
<tab>general</tab>
<label>Loyalty Points</label>
<frontend_type>text</frontend_type>
<sort_order>1002</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
<groups>
<config_points translate="label">
<label>Configuration</label>
<comment><![CDATA[
<script type="text/javascript">
checkExpirationPeriod = function() {
if ($('points_options_config_points_expiration_period').getValue() > 0) {
$('points_options_config_points_expiration_reminder').up(1).appear();
} else {
$('points_options_config_points_expiration_reminder').up(1).fade();
}
}
Event.observe(window, 'load', function() {
Event.observe('points_options_config_points_expiration_period', 'change', checkExpirationPeriod);
checkExpirationPeriod();
})
</script>
]]></comment>
as you can see, I write a small function which check one field's value to determine if show another one or not. I then link the onchange event to the function and trigger the function to show correct fields as the page is loaded.
For your needs, just add the condition in the js function.
Hope That Helps
Andrew's answer almost did the trick. I'm on 1.6.2.0 right now and I modified the initFields()
method in app\code\core\Mage\Adminhtml\Block\System\Config\Form.php
as follows:
if ($e->depends) {
foreach ($e->depends->children() as $dependent) {
Mage::log((array)$dependent);
$dependentId = $section->getName()
. '_' . $group->getName()
. '_' . $fieldPrefix
. $dependent->getName();
if ($dependent->hasChildren()) {
$dependentValue = (array) $dependent;
$dependentValue = array_values($dependentValue);
} else {
$dependentValue = (string) $dependent;
}
$shouldBeAddedDependence = true;
$dependentFieldName = $fieldPrefix . $dependent->getName();
$dependentField = $group->fields->$dependentFieldName;
/*
* If dependent field can't be shown in current scope and real dependent config value
* is not equal to preferred one, then hide dependence fields by adding dependence
* based on not shown field (not rendered field)
*/
if (!$this->_canShowField($dependentField)) {
$dependentFullPath = $section->getName()
. '/' . $group->getName()
. '/' . $fieldPrefix
. $dependent->getName();
if (is_array($dependentValue)) {
foreach ($dependentValue as $dependentOption) {
$shouldBeAddedDependence |= $dependentOption != Mage::getStoreConfig(
$dependentFullPath,
$this->getStoreCode()
);
}
} else {
$shouldBeAddedDependence = $dependentValue != Mage::getStoreConfig(
$dependentFullPath,
$this->getStoreCode()
);
}
}
if($shouldBeAddedDependence) {
$this->_getDependence()
->addFieldMap($id, $id)
->addFieldMap($dependentId, $dependentId)
->addFieldDependence($id, $dependentId, $dependentValue);
}
}
}
Also it's not necessary to edit the core files. I overrode the admin theme to insert my own version of form.js
and rewrote the two PHP classes using the config.xml
of a custom module.
精彩评论