Admin config: показывать поле в зависимости от выбранных значений множественного выбора

10

Я хочу отображать поля, основанные на выбранном вводе нескольких элементов ... следующий код просто работает, если выбрано только одно значение. Если я выберу более одного значения, будет показано только одно поле (сначала выбранное из исходной модели)

<enabled>
    <label>Enabled</label>
    ...
    <source_model>adminhtml/system_config_source_enabledisable</source_model>
</enabled>

<!-- this gives three options - shop, ebay, amazon -->
<channels>
    ...
    <frontend_type>multiselect</frontend_type>
    <source_model>module/system_config_source_channels</source_model>
    <depends>
        <enabled>1</enabled>
    </depends>
</channels>
<mail_template_shop>
    ...
    <depends>
        <enabled>1</enabled>
        <channels>shop</channels>
    </depends>
</mail_template_shop>
<mail_template_ebay>
    ...
    <depends>
        <enabled>1</enabled>
        <channels>ebay</channels>
    </depends>
</mail_template_ebay>

Связанный код:

Приложение / код / ​​ядро ​​/ Mage / Adminhtml / Block / Widget / Форма / элемент / Dependence.php

/**
 * Add misc configuration options to the javascript dependencies controller
 *
 * @param array $options
 * @return Mage_Adminhtml_Block_Widget_Form_Element_Dependence
 */
public function addConfigOptions(array $options)
{
    $this->_configOptions = array_merge($this->_configOptions, $options);
    return $this;
}

/**
 * HTML output getter
 * @return string
 */
protected function _toHtml()
{
    if (!$this->_depends) {
        return '';
    }
    return '<script type="text/javascript"> new FormElementDependenceController('
        . $this->_getDependsJson()
        . ($this->_configOptions ? ', ' . Mage::helper('core')->jsonEncode($this->_configOptions) : '')
        . '); </script>';
}

/**
 * Field dependences JSON map generator
 * @return string
 */
protected function _getDependsJson()
{
    $result = array();
    foreach ($this->_depends as $to => $row) {
        foreach ($row as $from => $value) {
            $result[$this->_fields[$to]][$this->_fields[$from]] = $value;
        }
    }
    return Mage::helper('core')->jsonEncode($result);
}

JS / маг / adminhtml / form.js

/**
 * Observer that watches for dependent form elements
 * If an element depends on 1 or more of other elements, it should show up only when all of them gain specified values
 */
FormElementDependenceController = Class.create();
FormElementDependenceController.prototype = {
    /**
     * Structure of elements: {
     *     'id_of_dependent_element' : {
     *         'id_of_master_element_1' : 'reference_value',
     *         'id_of_master_element_2' : 'reference_value'
     *         'id_of_master_element_3' : ['reference_value1', 'reference_value2']
     *         ...
     *     }
     * }
     * @param object elementsMap
     * @param object config
     */
    initialize : function (elementsMap, config)
    {
        if (config) {
            this._config = config;
        }
        for (var idTo in elementsMap) {
            for (var idFrom in elementsMap[idTo]) {
                if ($(idFrom)) {
                    Event.observe($(idFrom), 'change', this.trackChange.bindAsEventListener(this, idTo, elementsMap[idTo]));
                    this.trackChange(null, idTo, elementsMap[idTo]);
                } else {
                    this.trackChange(null, idTo, elementsMap[idTo]);
                }
            }
        }
    },

    /**
     * Misc. config options
     * Keys are underscored intentionally
     */
    _config : {
        levels_up : 1 // how many levels up to travel when toggling element
    },

    /**
     * Define whether target element should be toggled and show/hide its row
     *
     * @param object e - event
     * @param string idTo - id of target element
     * @param valuesFrom - ids of master elements and reference values
     * @return
     */
    trackChange : function(e, idTo, valuesFrom)
    {
        if (!$(idTo)) {
            return;
        }

        // define whether the target should show up
        var shouldShowUp = true;
        for (var idFrom in valuesFrom) {
            var from = $(idFrom);
            if (valuesFrom[idFrom] instanceof Array) {
                if (!from || valuesFrom[idFrom].indexOf(from.value) == -1) {
                    shouldShowUp = false;
                }
            } else {
                if (!from || from.value != valuesFrom[idFrom]) {
                    shouldShowUp = false;
                }
            }
        }

        // toggle target row
        if (shouldShowUp) {
            var currentConfig = this._config;
            $(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item) {
                // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
                if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)
                    && !(currentConfig.can_edit_price != undefined && !currentConfig.can_edit_price)) {
                    item.disabled = false;
                }
            });
            $(idTo).up(this._config.levels_up).show();
        } else {
            $(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item){
                // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
                if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)) {
                    item.disabled = true;
                }
            });
            $(idTo).up(this._config.levels_up).hide();
        }
    }
};
sv3n
источник
1
Привет @ sv3n, мы видим тебя не слишком много, все хорошо?
PЯINCƏ
ok @ sv3n круто, до скорой
встречи

Ответы:

12

Причина проблемы

Проблема, с которой вы сталкиваетесь, связана с функциональностью Javascript для получения значения атрибута множественного выбора.

Надежные поля Magento основаны на Javascript. Они создают JSON со всеми полями и значениями надежных полей, как показано ниже.

array (size=2)
  'brandlogo_general_pushonhover' => 
    array (size=2)
      'brandlogo_general_brandlogoenabled' => string '1' (length=1)
      'brandlogo_general_enableautoslide' => string '4' (length=1)
  'brandlogo_general_pager' => 
    array (size=2)
      'brandlogo_general_brandlogoenabled' => string '1' (length=1)
      'brandlogo_general_enableautoslide' => string '10' (length=4)

Когда вы выбираете параметр из атрибута множественного выбора, он возвращает только первое выбранное значение.

document.getElementById('demoSel').onchange = function(e) {
    alert(document.getElementById('demoSel').value);
}

Проверьте эту скрипку

Даже если вы выберете несколько вариантов, вы всегда получите первое значение выбранного параметра.

Решение проблемы

Вам нужно обновить JS-файл form.js, чтобы достичь желаемого.

Сначала вы должны добавить новую функцию, которая получит все выбранные значения Multiselect вместо единственного значения.

Добавьте новую функцию в ваш form.js

getSelectValues : function(select) {
    var result = [];
    var options = select && select.options;
    var opt;
    for (var i=0, iLen=options.length; i<iLen; i++) {
        opt = options[i];
        if (opt.selected) {
            result.push(opt.value);
        }
    }
    return result;
}

Теперь используйте эти значения для проверки вашей trackChangeфункции в том же файле. Заменить код ниже

for (var idFrom in valuesFrom) {
    var from = $(idFrom);
    if (valuesFrom[idFrom] instanceof Array) {
        if (!from || valuesFrom[idFrom].indexOf(from.value) == -1) {
            shouldShowUp = false;
        }
    } else {
        if (!from || from.value != valuesFrom[idFrom]) {
            shouldShowUp = false;
        }
    }
}

С этим кодом

for (var idFrom in valuesFrom) {
    var from = $(idFrom);
    if (from.tagName === 'SELECT' && from.className.indexOf('multiselect') > -1) {
        var elementValues = this.getSelectValues(from);
        if (!from || elementValues.indexOf(valuesFrom[idFrom]) <= -1) {
            shouldShowUp = false;
        }
     } else {
        if (valuesFrom[idFrom] instanceof Array) {
            if (!from || valuesFrom[idFrom].indexOf(from.value) == -1) {
                shouldShowUp = false;
            }
        } else {
            if (!from || from.value != valuesFrom[idFrom]) {
                shouldShowUp = false;
            }
        }
    }
}

И это должно работать для вас.

Джаймин Сутария
источник
Спасибо. Это объясняет это, но не решает. Проверено js/adminhtml/form.js, но решение пока не найдено ...
sv3n
2
@ sv3n, пожалуйста, проверьте обновленный ответ.
Джаймин Сутария