优雅的方式,根据“父”字段对有条件启用的“更多详细信息”表单字段进行分组

时间:2014-01-10 01:29:59

标签: javascript jquery html forms

我正在开发具有多组字段的大型表单。每个组都有一个'main'真/假下拉/单选按钮字段,当设置为true时,将启用该组中关联的“更多详细信息”字段。

我知道通常的做法是将变更处理程序上的JS绑定到每个组的“main”字段,然后根据“main”字段的值启用/禁用“more details”字段

由于存在许多这些组,因此将事件处理程序手动绑定到每个“主”字段似乎很耗时且重复。当然有更好的方法。我怎样才能优雅地实现这个功能?想象一下,data-option属性可以有效地用于此。

我的伪代码:

- On change event handler for all fields with data-group-parent
    - For all elements with data-group-child-of == this data-group-parent, set enabled value to 

还有其他建议吗?

2 个答案:

答案 0 :(得分:1)

这真的归结为你想要如何构建它,以及你想如何驱动它......

如果您只是隐藏或禁用表单的大部分内容,直到它们的主开关被抛出,那么您将节省大量的工作。

<form id="MyForm">
    <section>
        <header>
            <p>I would like to experience the best yams the world has to offer!</p>
            <select data-switch="gourmet-yams-of-the-world">
                <option value="1">true</option>
                <option value="0">false</option>
            </select>
        </header>
        <div class="big-ol-list-of-yam-options"
             data-controller="gourmet-yams-of-the-world"
             hidden>
            <!-- ... -->
        </div>
    </section>
</form>

这里你真正缺少的只是一个事件监听器,几行属性解析和一些querySelector魔术。

// listen for onchange, check if it's a "switch" that changed, and find the panel the switch controls

var isSwitch = function (el) { return el.hasAttribute("data-switch"); },
    getGroupName = function (el) { return el.getAttribute("data-switch"); },
    getGroup = function (root, groupName) {
        return root.querySelector("[data-controller=\"" + groupName + "\"]");
    },
    handleSwitch = function (evt) {
        var el = evt.target,
            switchEl = isSwitch(el),
            groupName, group, action;

        if (!switchEl) { return; }
        groupName = getGroupName(el);
        group = getGroup(MyForm, groupName);
        action = !!(+el.value); // converting it to a number (1 or 0, and then to Boolean)
        toggleGroup(group, action);
    };


MyForm.addEventListener("change", handleSwitch);

请注意,这并不能保证适用于所有浏览器。 有趣的是,不支持addEventListener的浏览器也难以冒充“改变”事件。

还有其他方法可以做到这一点。

就个人而言,我可能会使用这种事件处理的组合,但是使用JSON元数据构建实际表单......只是因为。

不是世界上绝对最好的解决方案,如果你正在使用ghettoIE(虽然有点jQuery可以提供帮助,我猜),而不是配置驱动的,不能保证工作 - 你仍然最终会构建它但是你现在正在使用HTML,但至于节省了数百名听众的挫败感,与替代方案相比,这将是一个简单,快速的解决方案。

答案 1 :(得分:1)

jQuery对元素集的工作如此普通,使用极少量的代码可以影响很多元素。想象一下,你有以下HTML:

Some info
<span class="more-details"></span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>
Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>

它显示了一些信息,然后是可点击元素(注意:您不必使用无线电/下拉列表),然后显示一些其他信息。我们希望最初隐藏其他信息,仅在用户点击链接时显示:

$('.more-details').text('Click for more...');
$('.more-info').hide();

完成此操作后,您可以通过单一功能将点击事件附加到所有可点击元素:

$('.more-details').click(function(){

    var $span = $(this);

    if ($span.text() == 'Click for more...') {
        $span.next().show();
        $span.text('Click for less...')
    } else {
        $span.next().hide();
        $span.text('Click for more...')
    }

})

抓住它:http://jsfiddle.net/Ckr85/

您不必使用数据属性 - 您可以按公共类组合组/元素。再次,使用“显示更多/更少”的单个链接比收音机/下拉菜单更加用户友好。