当我与多复选框下拉菜单交互时,我尝试通过触发 AJAX 请求来使用后端 Flask 服务器获取数据。本质上,我有两个下拉菜单,分别称为“选择日期”和“选择频道”。 “选择日期”下拉菜单对应于特定的 .parquet 文件,“选择频道”对应于这些 .parquet 文件的列标题。
但是,当我与其中一个下拉菜单交互时,另一个下拉菜单的事件也会被触发(甚至不与其交互)。我该如何避免这种情况?
我有以下 JS 脚本用于创建 MultiCheckbox 下拉菜单,我已将其另存为 select-checkbox.js:
$(document).ready(function () {
$(document).on("click", ".MultiCheckBox", function () {
var detail = $(this).next();
detail.show();
});
$(document).on("click", ".MultiCheckBoxDetailHeader input", function (e) {
e.stopPropagation();
var hc = $(this).prop("checked");
$(this).closest(".MultiCheckBoxDetail").find(".MultiCheckBoxDetailBody input").prop("checked", hc);
$(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
});
$(document).on("click", ".MultiCheckBoxDetailHeader", function (e) {
var inp = $(this).find("input");
var chk = inp.prop("checked");
inp.prop("checked", !chk);
$(this).closest(".MultiCheckBoxDetail").find(".MultiCheckBoxDetailBody input").prop("checked", !chk);
$(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
});
$(document).on("click", ".MultiCheckBoxDetail .cont input", function (e) {
e.stopPropagation();
$(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
var val = ($(".MultiCheckBoxDetailBody input:checked").length == $(".MultiCheckBoxDetailBody input").length)
$(".MultiCheckBoxDetailHeader input").prop("checked", val);
});
$(document).on("click", ".MultiCheckBoxDetail .cont", function (e) {
var inp = $(this).find("input");
var chk = inp.prop("checked");
inp.prop("checked", !chk);
var multiCheckBoxDetail = $(this).closest(".MultiCheckBoxDetail");
var multiCheckBoxDetailBody = $(this).closest(".MultiCheckBoxDetailBody");
multiCheckBoxDetail.next().UpdateSelect();
var val = ($(".MultiCheckBoxDetailBody input:checked").length == $(".MultiCheckBoxDetailBody input").length)
$(".MultiCheckBoxDetailHeader input").prop("checked", val);
});
$(document).mouseup(function (e) {
var container = $(".MultiCheckBoxDetail");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.hide();
}
});
});
var defaultMultiCheckBoxOption = { width: '220px', defaultText: 'Select Below', height: '200px' };
jQuery.fn.extend({
CreateMultiCheckBox: function (options) {
var localOption = {};
localOption.width = (options != null && options.width != null && options.width != undefined) ? options.width : defaultMultiCheckBoxOption.width;
localOption.defaultText = (options != null && options.defaultText != null && options.defaultText != undefined) ? options.defaultText : defaultMultiCheckBoxOption.defaultText;
localOption.height = (options != null && options.height != null && options.height != undefined) ? options.height : defaultMultiCheckBoxOption.height;
this.hide();
this.attr("multiple", "multiple");
var divSel = $("<div class='MultiCheckBox'>" + localOption.defaultText + "<span class='k-icon k-i-arrow-60-down'><svg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='sort-down' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512' class='svg-inline--fa fa-sort-down fa-w-10 fa-2x'><path fill='currentColor' d='M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41z' class=''></path></svg></span></div>").insertBefore(this);
divSel.css({ "width": localOption.width });
var detail = $("<div class='MultiCheckBoxDetail'><div class='MultiCheckBoxDetailHeader'><input type='checkbox' class='mulinput' value='-1982' /><div>Select All</div></div><div class='MultiCheckBoxDetailBody'></div></div>").insertAfter(divSel);
detail.css({ "width": parseInt(options.width) + 10, "max-height": localOption.height });
var multiCheckBoxDetailBody = detail.find(".MultiCheckBoxDetailBody");
this.find("option").each(function () {
var val = $(this).attr("value");
if (val == undefined)
val = '';
multiCheckBoxDetailBody.append("<div class='cont'><div><input type='checkbox' class='mulinput' value='" + val + "' /></div><div>" + $(this).text() + "</div></div>");
});
multiCheckBoxDetailBody.css("max-height", (parseInt($(".MultiCheckBoxDetail").css("max-height")) - 28) + "px");
},
UpdateSelect: function () {
var arr = [];
this.prev().find(".mulinput:checked").each(function () {
arr.push($(this).val());
});
this.val(arr);
},
});`
在 HTML 方面,我通过以下方式创建了两个名为“选择频道”和“选择日期”的下拉菜单:
<head>
<script>
$(document).ready(function () {
$("#test").CreateMultiCheckBox({ width: '230px', defaultText : 'Select Below', height:'250px' });
});
</script>
<script>
$(document).ready(function () {
$("#test_2").CreateMultiCheckBox({ width: '230px', defaultText : 'Select Below', height:'250px' });
});
</script>
</head>`
<body>
<div class="container">
<div class="side-container">
<!-- First Dropdown -->
<div class="mb-3" data-dropdown-type="channel">
<label for="exampleFormControlSelect1" class="form-label">Select Channel</label>
<select id="test">
{% for column in data %}
<option value="{{ column }}">{{ column }}</option>
{% endfor %}
</select>
</div>
<!-- Second Dropdown -->
<div class="mb-3" data-dropdown-type="date">
<label for="exampleFormControlSelect1" class="form-label">Select Date</label>
<select id="test_2">
{% for parquet_file in parquet_files %}
<option value="{{ parquet_file }}">{{ parquet_file }}</option>
{% endfor %}
</select>
</div>`
下拉菜单的选项是基于后端 Flask 服务器生成的。 现在,我尝试使用事件侦听器触发 Ajax 请求,以获取下拉菜单上所选选项的相应数据。我想从“选择日期”下拉菜单中获取所选数据的通道数据。但是,当我与其中一个下拉菜单交互时,即使不与其交互,我也会为另一个下拉菜单打印 console.log。我假设这是因为更改事件侦听器附加到整个文档(document.addEventListener(“change”,...))。这意味着每当文档中的任何位置发生任何更改事件(而不仅仅是在下拉列表中)时,都会触发事件侦听器。 我该如何解决? 以下是 fetchData 函数和发出 AJAX 请求的 JS 脚本:
function fetchData(selectedChannels, selectedFiles) {
console.log("Fetching data...");
console.log(selectedChannels)
console.log(selectedFiles)
// Make an AJAX request to the backend with selectedChannel and selectedFile
$.ajax({
url: "/fetch_data",
type: "POST",
data: JSON.stringify({ channels: selectedChannels, files: selectedFiles }),
contentType: "application/json",
success: function (response) {
console.log("Data received successfully:", response);
// Render the data received from the backend on the webpage
displayData(response);
},
error: function(xhr, status, error) {
console.error("Error fetching data:", error);
},
});
}
// Function to display the data on the webpage
function displayData(data) {
// You can update the DOM elements with the data received
// For example, create tables or charts to visualize the data
console.log(data);
}
这是事件监听器:
document.addEventListener("change", function (event) {
const target = event.target;
console.log("Event triggered.")
console.log(target)
var array = []
$("#test option").each(function(){
if($(this).is(":selected"))
{array.push($(this).val());}
});
console.log(array)
var array1 = []
$("#test_2 option").each(function(){
if($(this).is(":selected"))
{array1.push($(this).val());}
});
console.log(array1)
if (array.length >=1 && array1.length>=1) {
const selectedChannels = Array.from(array)//.map(checkbox => checkbox.value);
console.log(selectedChannels)
const selectedFiles = Array.from(array1)//.map(checkbox => checkbox.value);
console.log(selectedFiles)
fetchData(selectedChannels,selectedFiles);
}
else{
console.log("No match found")
}
});
</script>
将事件监听器直接注册到选择元素。
<script>
$(document).ready(function () {
$("#test").CreateMultiCheckBox({
defaultText: 'Select Below',
height:'250px',
width: '230px'
});
$("#test_2").CreateMultiCheckBox({
defaultText: 'Select Below',
height:'250px',
width: '230px'
});
$('#test, #test_2').change(function(evt) {
// Your listener code here!
});
});
</script>
事件可能不会被触发,因为您正在
UpdateSelect
中通过 JavaScript 更新选择元素。在这种情况下,当选择元素更新时手动触发事件。
const event = new Event('change');
selectElem.dispatchEvent(event);