JavaScript 中默认选项选择时未触发下拉更改事件

问题描述 投票:0回答:1

我正在使用 vanilla JavaScript 开发动态表过滤功能,其中我使用下拉菜单来过滤表中显示的数据。每个下拉列表都有一个默认选项(带有空字符串值)和与数据列相对应的其他几个选项。我的问题是,在选择不同的选项后,重新选择默认选项时,更改事件似乎不会触发。这可以防止表重置为其原始的、未过滤的状态。

这是我的下拉 HTML 在进行选择之前和之后的简化版本:

<th>
<select id="filter-findingStatus" class="filter-dropdown" data-columnname="findingStatus">
    <option value="">All findingStatus</option>
    <option value="in_progress">in_progress</option>
    <option value="false_positive">false_positive</option>
    <option value="closed">closed</option>
    <option value="ignored">ignored</option>
    <option value="new">new</option>
</select>

做出选择后:

<th>
    <select id="filter-findingStatus" class="filter-dropdown" data-columnname="findingStatus">
        <option value="">All findingStatus</option>
        <option value="ignored">ignored</option>
    </select>
</th>

这是 JavaScript 部分,我在其中监听更改事件并尝试过滤表:它是构造函数表类的一部分。

class Table {
constructor(tableId, headers) {
    this.tableId = tableId;
    this.headers = headers;
    this.uniqueValues = {};
    this.currentFilters = {};
    this.originalData = [];
    this.loadedData = [];
    this.currentlyLoadedCount = 0;
    this.loadIncrement = 20;

    console.info(`Table ID: ${this.tableId}`);
    const tableIdElement = document.getElementById(tableId);

    // Check if the table element exists
    if (!tableIdElement) {
        console.error(`Table not found for tableId: ${tableId}`);
        return;
    }
    if (tableIdElement) {
        const scrollContainer = tableIdElement.closest('.table-scroll-container');
        if (scrollContainer) {
            scrollContainer.addEventListener('scroll', () => {
                if ((scrollContainer.offsetHeight + scrollContainer.scrollTop) >= scrollContainer.scrollHeight) {
                    this.loadMoreRows();
                }
            });
        } else {
            console.error(`Scroll container not found for table with id: ${this.tableId}`);
        }
    } else {
        console.error(`Table with id: ${this.tableId} not found`);
    }
    const dataBody = document.getElementById(this.tableId).querySelector('tbody');
    if (!dataBody) {
        console.error(`Table body not found for ID: ${this.tableId}`);
    }
    dataBody.innerHTML = '';
    // Get all filter dropdowns
    const filterDropdowns = document.querySelectorAll('.filter-dropdown');

    filterDropdowns.forEach(dropdown => {
        console.log(`Adding event listener to dropdown with column name: ${dropdown.dataset.columnname}`);
        dropdown.addEventListener('change', (event) => {
            console.log('Dropdown change event triggered', event);
            // Get the selected value
            const selectedValue = event.target.value;
            
            // Get the column name from the dropdown's data-columnName attribute
            const columnName = dropdown.dataset.columnname;
            
            // Call the filterTables method with the column name and selected value
            this.filterTables(columnName, selectedValue);
        });
    });
}

我的过滤表方法:

filterTables(columnName, selectedValue) {
    console.log(`Filtering tables for column: ${columnName}, selected value: ${selectedValue}`);
    
    // If the selected value is the default value, remove the filter for this column
    if (selectedValue === '') {
        console.log(`Default (empty) value selected for column: ${columnName}. Removing filter for this column.`);
        delete this.currentFilters[columnName];
        // Reset the loadedData to the originalData
        this.loadedData = [...this.originalData];
    } else {
        // Otherwise, update the current filters
        console.log(`Non-default value selected for column: ${columnName}. Updating filter for this column.`);
        this.currentFilters[columnName] = selectedValue;
    }

    console.log(`Current filters:`, this.currentFilters);

    // Update the dropdown to show the currently selected value
    const dropdown = document.querySelector(`.filter-dropdown[data-columnName="${columnName}"]`);
    if (dropdown) {
        dropdown.value = selectedValue;
    }

    // Apply all filters to the originalData array
    this.loadedData = this.originalData.filter(item => {
        for (let column in this.currentFilters) {
            const cellValue = item[column] || '';
            const filterValue = this.currentFilters[column];
            if (filterValue !== '' && !cellValue.includes(filterValue)) {
                return false; // Exclude this item if it doesn't match the filter
            }
        }
        return true; // Include this item if it matches all filters
    });

    console.log(`Loaded data after applying filters:`, this.loadedData);

    // Clear the table
    const dataBody = document.getElementById(this.tableId).querySelector('tbody');
    dataBody.innerHTML = '';

    // Reset the currentlyLoadedCount
    this.currentlyLoadedCount = 0;

    // Load the first batch of rows
    this.loadMoreRows();

    // Store the unique filter options based on the currently filtered data
    this.storeAllUniqueFilterOptions(this.loadedData);
}

这两种方法是我获取下拉选项并附加它们的方法:

storeAllUniqueFilterOptions(data) {
    // Reset the uniqueValues object
    this.uniqueValues = {};
    data.forEach(item => {
        this.headers.forEach(header => {
            const cellValue = item[header] || '';
            if (!this.uniqueValues[header]) {
                this.uniqueValues[header] = new Set();
            }
            this.uniqueValues[header].add(cellValue);
        });
    });
    this.populateFilterDropdowns();
}
populateFilterDropdowns() {
    for (const [key, valueSet] of Object.entries(this.uniqueValues)) {
        const dropdown = document.querySelector(`.filter-dropdown[data-columnName="${key}"]`);
        if (dropdown) {
            // Preserve the default option so it can be re-added after clearing
            const defaultOption = dropdown.querySelector('option[value=""]');
            // Clear old options
            dropdown.innerHTML = '';
            
            // Re-append the default option
            if (defaultOption) {
                dropdown.appendChild(defaultOption.cloneNode(true)); // Append a cloned node of the default option
            }
            // Populate filter dropdowns with unique values
            valueSet.forEach(value => {
                const option = document.createElement('option');
                option.value = value;
                option.textContent = value;
                dropdown.appendChild(option);
            });

            }
    }
}

但是,当我选择默认选项时,不会触发任何日志,包括更改事件内的日志。这意味着在这种情况下该事件不会触发,尽管它对于所有其他选项都可以正常工作。此行为会阻止数据按预期重置。

我尝试过的:

验证事件监听器是否正确附加到所有其他选项 在控制台中检查 JavaScript 错误(未发现)。 选择默认选项时手动触发事件(不理想并且无法使其按预期工作)。

我的问题:即使重新选择默认选项,如何确保更改事件触发,以便我的表可以重置为其原始的、未过滤的状态?

任何见解或建议将不胜感激!

javascript html event-handling
1个回答
0
投票

能够找到解决方案,即使在应用过滤器后,默认值仍保持选中状态,使其不可选择。所以我只需要在填充 filterDropdowns 结束时重置之前选择的值。

populateFilterDropdowns() {
    for (const [key, valueSet] of Object.entries(this.uniqueValues)) {
        const dropdown = document.querySelector(`.filter-dropdown[data-columnName="${key}"]`);
        if (dropdown) {
            // Remember the currently selected value
            const selectedValue = dropdown.value;

            // Preserve the default option so it can be re-added after clearing
            // Clear old options
            dropdown.innerHTML = '';

            // Create and append the default option
            this.createDefaultOption(dropdown, key);

            // Populate filter dropdowns with unique values
            valueSet.forEach(value => {
                const option = document.createElement('option');
                option.value = value;
                option.textContent = value;
                dropdown.appendChild(option);
            });

            // Reselect the previously selected value
            dropdown.value = selectedValue;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.