我如何修改此 jQuery 以在下拉列表中动态显示和隐藏相关选择选项?
How can I modify this jQuery to dynamically show and hide dependent selection options in drop-down?
在这个例子中,我有一系列 3 个 select 下拉菜单。将相同的 class(“group-1”)应用于每个以表明它们是相关的(并允许在同一页面上有多个 select 组)。 “data-parent”属性应用于 select 以建立 1:1 parent/child 关系。 “data-parent”属性应用于建立many:many关系的选项。
我的目标是创建一段动态 jQuery 代码,这样我就不必通过 id 或 class 明确识别行为,而是通过选项值和数据父值.
我的问题:
- 第三个下拉列表根本没有更新。我认为它们中的一些可能具有多个数据父值(由 space 分隔),但即使我将它们更改为全部只有一个,它仍然不会随着更改而更新第二个下拉列表。
- 我不确定如何在第三个下拉列表的选项中实现“许多”数据父值。拆分字符串,创建数组,查看数组中是否有值?
- 如何通过更改父下拉菜单将第二个和第三个下拉菜单重置为“默认”值?例如,如果我从第一个中选择“Cookies”,则第二个中会出现“1 dozen”和“2 dozen”。但是,如果我 select“1 打”然后将第一个框更改为“蛋糕”,则“1 打”仍然 selected,即使“Sheet”和“Round”是唯一的下拉列表中的可用选项。我想让它重置为默认值(“甜点...”)。
代码在下面,这是我的工作 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>
在此先感谢您提供的所有帮助!另外,欢迎提出改进建议。
我不知道这段代码的上下文,所以我不知道这种“嵌套”选项和选择的模式是否是最佳解决方案。但这是我的 javascript 版本,它似乎实现了问题中的要求。我会评论相关的变化,这样我的思维过程就很清楚了。我还为隐藏 class 添加了 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 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;
}
不知道是不是我评论过头了,有什么不明白的地方欢迎评论。
您可以使用 attributeContainsWord (~) 将多个值与一个词匹配。因此,在下面的代码中,我使用 $(this).children("option[data-parent~='" + selVal + "']").show();
来显示与 selVal
匹配的选项。此外,我还使用 prop('selectedIndex', 0);
将 select 重置为默认值。
演示代码 :
$(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>
在这个例子中,我有一系列 3 个 select 下拉菜单。将相同的 class(“group-1”)应用于每个以表明它们是相关的(并允许在同一页面上有多个 select 组)。 “data-parent”属性应用于 select 以建立 1:1 parent/child 关系。 “data-parent”属性应用于建立many:many关系的选项。
我的目标是创建一段动态 jQuery 代码,这样我就不必通过 id 或 class 明确识别行为,而是通过选项值和数据父值.
我的问题:
- 第三个下拉列表根本没有更新。我认为它们中的一些可能具有多个数据父值(由 space 分隔),但即使我将它们更改为全部只有一个,它仍然不会随着更改而更新第二个下拉列表。
- 我不确定如何在第三个下拉列表的选项中实现“许多”数据父值。拆分字符串,创建数组,查看数组中是否有值?
- 如何通过更改父下拉菜单将第二个和第三个下拉菜单重置为“默认”值?例如,如果我从第一个中选择“Cookies”,则第二个中会出现“1 dozen”和“2 dozen”。但是,如果我 select“1 打”然后将第一个框更改为“蛋糕”,则“1 打”仍然 selected,即使“Sheet”和“Round”是唯一的下拉列表中的可用选项。我想让它重置为默认值(“甜点...”)。
代码在下面,这是我的工作 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>
在此先感谢您提供的所有帮助!另外,欢迎提出改进建议。
我不知道这段代码的上下文,所以我不知道这种“嵌套”选项和选择的模式是否是最佳解决方案。但这是我的 javascript 版本,它似乎实现了问题中的要求。我会评论相关的变化,这样我的思维过程就很清楚了。我还为隐藏 class 添加了 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 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;
}
不知道是不是我评论过头了,有什么不明白的地方欢迎评论。
您可以使用 attributeContainsWord (~) 将多个值与一个词匹配。因此,在下面的代码中,我使用 $(this).children("option[data-parent~='" + selVal + "']").show();
来显示与 selVal
匹配的选项。此外,我还使用 prop('selectedIndex', 0);
将 select 重置为默认值。
演示代码 :
$(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>