You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Flask应用结合JavaScript实现下拉选项表格多列筛选

多下拉菜单联合筛选表格实现方案

核心需求

  • 选中国家下拉菜单选项时,自动过滤表格中国家字段匹配的所有行
  • 支持多列配置多个下拉菜单,实现多条件联合筛选
  • 兼容现有Flask+原生JS技术栈,无需引入第三方依赖

原有问题点

之前使用addEventListener('click')绑定下拉菜单交互无法实现完整功能,核心原因是下拉框的click事件会在点击展开选项列表时就触发,此时用户还未选中目标选项,拿不到正确的筛选值,应该绑定change事件,仅当选中值发生变化时执行筛选逻辑。


现有代码基础

Flask后端代码

app = Flask(__name__)
test_data = [['jack', 23, 'china', 'https://www.google.com'],
             ['jill', 22, 'canada', 'https://www.cnn.com'],
             ['john', 24, 'canada', 'https://www.cnn.com'],
             ['jane', 30, 'australia', 'https://www.bbc.com']]

test_df = pd.DataFrame(test_data, columns=['name', 'age', 'country', 'link'])
test_df = test_df.to_dict(orient='index')
@app.route("/hello")
def index():
    return render_template("index.html", test_df=test_df)

HTML模板结构

<div class="container">
    <label for="country">Countries</label>
    <form class="form">
        <div class="form__group">
            <select id="country" name="country" data-dropdown>
                <option value="">Please select a country</option>
                <option value="australia">Australia</option>
                <option value="canada">Canada</option>
                <option value="china">China</option>
            </select>
        </div>
    </form>
</div>

<table class="table">
    <tbody id="myTable">
    </tbody>
</table>

初始JS逻辑

var mydata = JSON.parse('{{ test_df|tojson }}');
var countrySelector = document.getElementById('country');
// but what next?

buildTable(mydata)
function buildTable(data) {
    var table = document.getElementById('myTable')
    table.innerHTML = ''
    for (var key in data) {
        var row = `<tr>
                    <td>${data[key].name}</td>
                    <td>${data[key].age}</td>
                    <td><a href="${data[key].link}" target='_blank'>${data[key].country}</a></td>
               </tr>`
        table.innerHTML += row
    }
}

实现方案

核心逻辑

  • 单独存储后端返回的全量原始数据,所有筛选操作都基于这份原始数据执行,避免多次筛选后数据丢失
  • 统一给所有带data-dropdown标识的下拉框绑定change事件,任意下拉框值变化时触发筛选
  • 每次筛选时先收集所有已选中的有效筛选条件,再遍历原始数据匹配全部条件,最终用匹配结果重新渲染表格
  • 逻辑天然支持扩展,后续新增筛选下拉框无需修改JS代码,只要按规则配置HTML属性即可自动接入联合筛选

修改后完整JS代码

// 存储全量原始数据,作为筛选的数据源
const originalData = JSON.parse('{{ test_df|tojson }}');
// 首次加载渲染全量数据
buildTable(Object.values(originalData));

// 给所有标记了data-dropdown的筛选下拉框绑定change事件
document.querySelectorAll('[data-dropdown]').forEach(selector => {
    selector.addEventListener('change', applyFilters);
});

// 筛选执行函数
function applyFilters() {
    // 收集当前所有生效的筛选条件:键为对应数据字段名,值为选中的筛选值
    const activeFilters = {};
    document.querySelectorAll('[data-dropdown]').forEach(selector => {
        const matchField = selector.name;
        const selectedVal = selector.value.trim();
        if (selectedVal) activeFilters[matchField] = selectedVal;
    });

    // 遍历原始数据,匹配所有生效筛选条件
    const filteredResult = Object.values(originalData).filter(item => {
        return Object.entries(activeFilters).every(([field, filterVal]) => {
            // 统一转小写匹配,避免大小写差异导致匹配失败
            return String(item[field]).toLowerCase() === filterVal.toLowerCase();
        });
    });

    // 用筛选结果重新渲染表格
    buildTable(filteredResult);
}

// 表格渲染函数
function buildTable(data) {
    const table = document.getElementById('myTable');
    table.innerHTML = '';
    data.forEach(row => {
        const rowHtml = `<tr>
                    <td>${row.name}</td>
                    <td>${row.age}</td>
                    <td><a href="${row.link}" target='_blank'>${row.country}</a></td>
               </tr>`;
        table.innerHTML += rowHtml;
    });
}

多列筛选扩展方法

后续需要新增其他字段的筛选下拉框时,不需要修改任何JS逻辑,只要在HTML中新增对应select标签,满足两个规则即可自动接入联合筛选:

  • 给select标签添加data-dropdown属性
  • 给select标签设置name属性,属性值和数据中对应字段名完全一致

示例:新增年龄筛选下拉框代码

<div class="form__group">
    <label for="age">Age</label>
    <select id="age" name="age" data-dropdown>
        <option value="">Please select age</option>
        <option value="22">22</option>
        <option value="23">23</option>
        <option value="24">24</option>
        <option value="30">30</option>
    </select>
</div>

可选优化

  • 如果需要支持模糊匹配,只需要把筛选判断逻辑从全等判断改为包含判断即可:
    return String(item[field]).toLowerCase().includes(filterVal.toLowerCase());
    
  • 如果需要支持范围筛选(比如年龄区间),只需要在applyFilters函数里扩展对应字段的匹配逻辑即可

内容的提问来源于stack exchange,提问作者kodikai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 22:45:39