如何修改此 jQuery 以在下拉列表中动态显示和隐藏相关选择选项?

Posted

技术标签:

【中文标题】如何修改此 jQuery 以在下拉列表中动态显示和隐藏相关选择选项?【英文标题】:How can I modify this jQuery to dynamically show and hide dependent selection options in drop-down? 【发布时间】:2020-11-25 14:20:16 【问题描述】:

在此示例中,我有一系列 3 个选择下拉菜单。相同的类(“group-1”)应用于每一个以表明它们是相关的(并允许在同一页面上选择多个组)。将“data-parent”属性应用于选择以建立 1:1 的父/子关系。 “data-parent”属性应用于建立many:many关系的选项。

我的目标是创建一段动态的 jQuery 代码,这样我就不必通过 id 或 class 明确地识别行为,而是通过选项值和 data-parent 值。

我的问题:

    第三个下拉菜单根本不更新。我认为其中一些可能具有多个数据父值(由空格分隔),但即使我将它们更改为只有一个,它仍然不会随着对第二个下拉列表的更改而更新. 我不确定如何在第三个下拉列表的选项中实现“许多”数据父值。拆分字符串,创建一个数组,查看值是否在数组中? 如何通过更改父下拉菜单将第二个和第三个下拉菜单重置为“默认”值?例如,如果我从第一个中选择“Cookies”,那么第二个中会出现“1打”和“2打”。但是,如果我选择“一打”,然后将第一个框更改为“蛋糕”,即使“表”和“圆形”是下拉菜单中唯一可用的选项,“一打”仍然处于选中状态。我希望它重置为默认值(“甜点...”)。

代码如下,这是我的工作 jsfiddle:https://jsfiddle.net/rwh4z623/20/

$(document).ready(function()
    $(".hide").children("option").hide();
    $("select").on('change', function()
        var selClass = $(this).attr("class");
        var selName = $(this).attr("name");
        var selVal = $(this).children("option:selected").val();
        $("select."+selClass+"[data-parent='"+selName+"']").each(function()
            $(this).children("option[data-parent='"+selVal+"']").show();
            $(this).children("option[data-parent!='"+selVal+"']").hide();
        );
    );
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="group-1" name="categories">
    <option value="" selected="selected">Please select...</option>
    <option value="cookie">Cookies</option>
    <option value="cake">Cakes</option>
    <option value="icecream">Ice Cream</option>
</select>

<select class="group-1 hide" name="desserts" data-parent="categories">
    <option value="" selected="selected">Desserts...</option>
    <option value="1-dozen" data-parent="cookie">1 dozen</option>
    <option value="2-dozen" data-parent="cookie">2 dozen</option>
    <option value="sheet" data-parent="cake">Sheet</option>
    <option value="round" data-parent="cake">Round</option>
    <option value="pint" data-parent="icecream">Pint</option>
</select>

<select class="group-1 hide" name="flavors" data-parent="desserts">
    <option value="" selected="selected">Flavors...</option>
    <option value="choc-chip" data-parent="1-dozen 2-dozen">Chocolate Chip</option>
    <option value="oatmeal" data-parent="1-dozen 2-dozen">Oatmeal</option>
    <option value="yellow" data-parent="sheet round">Yellow</option>
    <option value="red-velvet" data-parent="sheet">Red Velvet</option>
</select>

提前感谢您的任何帮助!另外,欢迎提出改进建议。

【问题讨论】:

【参考方案1】:

您可以使用attributeContainsWord (~) 将多个值与一个单词进行匹配。所以,在下面的代码中,我使用$(this).children("option[data-parent~='" + selVal + "']").show(); 显示与selVal 匹配的选项。此外,我使用prop('selectedIndex', 0); 将选择重置为默认值。

演示代码

$(document).ready(function() 
  $(".hide").children("option").hide();
  $("select").on('change', function() 
    //checking if dropdown is categories
    if ($(this).attr("name") == "categories") 
      //reset other to default
      $('select[name=desserts]').prop('selectedIndex', 0);
      $('select[name=flavors]').prop('selectedIndex', 0);
    

    var selClass = $(this).attr("class");
    var selName = $(this).attr("name");
    var selVal = $(this).children("option:selected").val();
    //check if name != desserts
    if ($(this).attr("name") != "desserts") 
      //hide option of flavour
      $("select[name=flavors]").children("option").hide();
      //loop and show desire values
      $("select." + selClass + "[data-parent='" + selName + "']").each(function() 
        $(this).children("option[data-parent='" + selVal + "']").show();
        $(this).children("option[data-parent!='" + selVal + "']").hide();
      );

     else 
      //hide options
      $("select[name=flavors]").children("option").hide();
      //loop through flavours
      $("select[name=flavors]").each(function() 
        //use " ~ " to see if the selval matches with values 
        $(this).children("option[data-parent~='" + selVal + "']").show();

      );

    
  );
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="group-1" name="categories">
  <option value="" selected="selected">Please select...</option>
  <option value="cookie">Cookies</option>
  <option value="cake">Cakes</option>
  <option value="icecream">Ice Cream</option>
</select>

<select class="group-1 hide" name="desserts" data-parent="categories">
  <option value="" selected="selected">Desserts...</option>
  <option value="1-dozen" data-parent="cookie">1 dozen</option>
  <option value="2-dozen" data-parent="cookie">2 dozen</option>
  <option value="sheet" data-parent="cake">Sheet</option>
  <option value="round" data-parent="cake">Round</option>
  <option value="pint" data-parent="icecream">Pint</option>
</select>

<select class="group-1 hide" name="flavors" data-parent="desserts">
  <option value="" selected="selected">Flavors...</option>
  <option value="choc-chip" data-parent="1-dozen 2-dozen">Chocolate Chip</option>
  <option value="oatmeal" data-parent="1-dozen 2-dozen">Oatmeal</option>
  <option value="yellow" data-parent="sheet round">Yellow</option>
  <option value="red-velvet" data-parent="sheet">Red Velvet</option>
</select>

【讨论】:

这个解决方案的问题(对我来说)是我试图避免在 javascript 中使用特定的标识符,因为页面上会有 6 或 7 个“组”。我希望使用“group-#”类和 data-parent 属性在页面上创建关系,让 JS 是动态的。【参考方案2】:

我不知道这段代码的上下文,所以我不知道这种“嵌套”选项和选择模式是否是最佳解决方案。但这是我的 javascript 版本,似乎实现了问题中的要求。我会评论相关的变化,这样我的思考过程就很清楚了。我还为隐藏类添加了 css,因为它不在 jsfiddle 中。

$(document).ready(function () 
    $("select").on('change', function () 
        var selClass = $(this).attr("class");
        var selName = $(this).attr("name");
        var selVal = $(this).children("option:selected").val();

        //Call the update function with the data of the changed Select
        updateRecursivly(selClass, selName, selVal);

        //Recursive function to update all selects, this allows for multiple "child" selects per select and an in theory infinite "tree" of selects
        function updateRecursivly(selClass, selName, selVal) 
            //Search "children" of the parent select
            var children = $("select." + selClass + "[data-parent='" + selName + "']");
            if (children.length) 
                children.each(function () 
                    //Hide all options in the "child" select
                    $(this).children("option[data-parent]").hide();
                    //if selVal is an empty string, the default option is selected and we should just hide the "child" select
                    if (selVal !== "") 
                        //Get all options that contain (*=) selVal in "data-parent"
                        var options = $(this).children("option[data-parent*='" + selVal + "']");
                        //If there are possible options show the select and the possible options. Else hide select
                        if (options.length) 
                            $(this).removeClass('hide');
                            options.show();
                         else 
                            $(this).addClass('hide');
                        
                     else 
                        $(this).addClass('hide');
                    
                    //If the select is updated, the options should be reset. Any selected is reset and the first is selected
                    //From here https://***.com/a/16598989/14040328 this is apparently safer against reset events than other solutions
                    $(this).children("option:selected").prop("selected", false);
                    $(this).children("option:first").prop("selected", "selected");

                    //Get the name of the select
                    var childName = $(this).attr("name");

                    //Update the Child select
                    updateRecursivly(selClass, childName, "");
                );
            
        
    );
);
.hide 
  display: none;

我不确定我是否过度使用 cmets,如果有任何不清楚的地方欢迎评论。

【讨论】:

这太完美了!我刚刚做了一个快速测试,添加了更多“链式”下拉菜单,以及额外的选择框组,它的工作方式完全符合我的设想。谢谢!

以上是关于如何修改此 jQuery 以在下拉列表中动态显示和隐藏相关选择选项?的主要内容,如果未能解决你的问题,请参考以下文章

基于其他下拉列表的 ajax 和 jQuery 动态下拉列表(来自数据库的数据)

如何使用 jquery 和 php 从动态数据中设置默认下拉列表?

如何在 Jquery 中为动态下拉列表创建循环?

jQuery动态加载select下拉列表

根据下拉列表的值隐藏和显示一行表格 - jquery

当每个下拉列表动态创建ID时,jquery选择选项数据和值[关闭]