处理基于矩阵的表单元素关系

时间:2014-03-09 12:59:15

标签: javascript jquery forms

我想听听您对如何解决我遇到的有关复杂行为的表单的意见和想法。

想象一下包含大约的搜索表单。在用户的输入过程中动态改变的30个输入元素/文本,选择,复选框等。例如。如果更改第一个选择,则某些字段必须更改为隐藏,某些字段必须更改为必需等等。字段关系映射到Excel中的矩阵中,后端将处理此信息并为前端提供此信息- 我。生成的表单字段可以由自定义类/数据属性提供,我可能会获得一个带有关系的JSON,并从那时起自己处理所有内容。这些关系将来可能会发生变化,或者至少应用程序必须为此做好准备,因此还需要考虑这些关系。 JQuery是可用的,如果需要的话我也可以使用一些Angular / Backbone类型的框架。

我是一名初级前任开发人员,说实话,我还没有找到一个可靠的解决方案,所以我很感激每一个发人深省的意见:)

提前致谢!

1 个答案:

答案 0 :(得分:1)

我从受这些关系影响的输入元素的角度定义了关系。此结构允许更多灵活性,包括支持检查多个选择框的值以及使用类似于ANDOR语句的逻辑。这是一个工作示例http://jsfiddle.net/bxTLR/

此代码以一个Javascript对象开头,该对象包含关系的定义,您可以使用返回JSON的AJAX调用来获取该关系。然后,它将此信息处理为输入元素的数据属性,并将监听器附加到选择框的change事件。

input1定义的关系:

    如果input1 value1 ,则需要
  • select1 如果input1 value2
  • ,则会隐藏
  • select1

input2定义的关系:

    如果input2 value2 select2 value3 ,则需要
  • select2 如果input2 value2 select3 value3
  • ,则会隐藏
  • select3

input3定义的关系:

    如果input3 value1 select1 value1 select2 ,则需要
  • select3值2
  • 如果input3 value2 select1 value2 select2 ,则隐藏
  • select3值1

input4定义的关系:

    如果input4 value1 select1 value2 select2 ,则需要
  • select3值1
  • 如果input4 value2 select1 value1 select2 ,则隐藏
  • select3值2

input5定义的关系:

    如果(input5 value1 且(select1 value1 select2 <),则需要
  • select2 strong> value2 )和(select3 value1 select3 value2 ))或(select1是< strong> value1 select3 value3
  • 如果(input5 value2 且(select1 value1 select2为<},则隐藏
  • select2 strong> value2 )和(select3 value1 select3 value2 ))或(select1是< strong> value2 且select3 value3

HTML选择框:

<div>
    <label>Select 1</label>
    <select id="select1" class="trigger">
        <option value="value1">Value 1</option>
        <option value="value2">Value 2</option>
    </select>
</div>
<div>
    <label>Select 2</label>
    <select id="select2" class="trigger">
        <option value="value1">Value 1</option>
        <option value="value2">Value 2</option>
    </select>
</div>
<div>
    <label>Select 3</label>
    <select id="select3" class="trigger">
        <option value="value1">Value 1</option>
        <option value="value2">Value 2</option>
        <option value="value3">Value 3</option>
    </select>
</div>

HTML输入元素:

<div>
    <label>Input 1</label>
    <input id="input1" type="text" />
</div>
<div>
    <label>Input 2</label>
    <input id="input2" type="text" />
</div>
<div>
    <label>Input 3</label>
    <input id="input3" type="text" />
</div>
<div>
    <label>Input 4</label>
    <input id="input4" type="text" />
</div>
<div>
    <label>Input 5</label>
    <input id="input5" type="text" />
</div>

CSS:

div.required input {
    border-color: #f00;
}
div.hidden {
    display: none;
}

关系的JSON:

var relationsJSON = {
    "input1": {
        requiredIf: [{
            "select1": ["value1"]
        }],
        hiddenIf: [{
            "select1": ["value2"]
        }]
    },
    "input2": {
        requiredIf: [{
            "select2": ["value2", "value3"]
        }],
        hiddenIf: [{
            "select3": ["value2", "value3"]
        }]
    },
    "input3": {
        requiredIf: [{
            "select1": ["value1"],
            "select2": ["value1"],
            "select3": ["value2"]
        }],
        hiddenIf: [{
            "select1": ["value2"],
            "select2": ["value2"],
            "select3": ["value1"]
        }]
    },
    "input4": {
        requiredIf: [{
            "select1": ["value1"],
            "select2": ["value2"],
            "select3": ["value1"]
        }],
        hiddenIf: [{
            "select1": ["value2"],
            "select2": ["value1"],
            "select3": ["value2"]
        }]
    },
    "input5": {
        requiredIf: [{
            "select1": ["value1"],
            "select2": ["value1", "value2"],
            "select3": ["value1", "value2"]
        }, {
            "select1": ["value1"],
            "select3": ["value3"]
        }],
        hiddenIf: [{
            "select1": ["value2"],
            "select2": ["value1", "value2"],
            "select3": ["value1", "value2"]
        }, {
            "select1": ["value2"],
            "select3": ["value3"]
        }]
    }
};

Javascript函数:

function storeRelation($input, relationName, relation) {
    var requiredIfOutput = [];
    var requiredIfClasses = [];
    $.each(relation, function(index, condition) {
        var conditionOutput = [];
        $.each(condition, function(selectID, values) {
            requiredIfClasses.push(relationName + '-' + selectID);
            conditionOutput.push('"' + selectID + '":["' + values.join('","') + '"]');
        });
        requiredIfOutput.push('{' + conditionOutput.join(',') + '}');
    });
    $input.addClass(requiredIfClasses.join(' '));
    $input.attr('data-' + relationName, '[' + requiredIfOutput.join(',') + ']');
}

function testRelation($input, relationName) {
    var requiredIfData = $.parseJSON($input.attr('data-' + relationName));
    var hasValidCondition = false;
    $.each(requiredIfData, function(index, condition) {
        var isValidCondition = true;
        $.each(condition, function(selectID, values) {
            var hasValidValue = false;
            var $requiredIfSelect = $('#' + selectID);
            $.each(values, function(index, value) {
                if ($requiredIfSelect.val() == value) {
                    hasValidValue = true;
                    return false;
                }
            });
            if (!hasValidValue) {
                isValidCondition = false;
                return false;
            }
        });
        if (isValidCondition) {
            hasValidCondition = true;
            return false;
        }
    });
    return hasValidCondition;
}

准备好Javascript文档:

$(document).ready(function() {

    $.each(relationsJSON, function(inputID, relations) {
        var $input = $('#' + inputID);
        if (relations.requiredIf != 'undefined') {
            storeRelation($input, 'required-if', relations.requiredIf);
        }
        if (relations.hiddenIf != 'undefined') {
            storeRelation($input, 'hidden-if', relations.hiddenIf);
        }
    });

    $('select.trigger').each(function() {
        var $select = $(this);
        $select.on('change', function() {

            var $requiredIfInputs = $('.required-if-' + $select.attr('id'));
            $requiredIfInputs.each(function() {
                var $input = $(this);
                var $container = $input.parent();
                if (testRelation($input, 'required-if')) {
                    $container.addClass('required');
                } else {
                    $container.removeClass('required');
                }
            });

            var $hiddenIfInputs = $('.hidden-if-' + $select.attr('id'));
            $hiddenIfInputs.each(function() {
                var $input = $(this);
                var $container = $input.parent();
                if (testRelation($input, 'hidden-if')) {
                    $container.addClass('hidden');
                } else {
                    $container.removeClass('hidden');
                }
            });

        });
        $select.trigger('change');
    });

});