如何以HTMX风格通过下拉菜单筛选FastAPI生成的表格?
方案一:前端本地直接筛选(无需后端改动)
适合数据量不大的场景,页面加载完成后直接在浏览器内完成筛选,无需请求后端。
步骤1:给表格行添加标识属性
修改gpio.html,为每个表格行添加data-gpio属性,用来标记该行对应的GPIO值:
{% for gpio in gpios %} <tr data-gpio="{{ gpio.gpio }}"> <td class="border"> {{ gpio.gpio }} </td> <td class="border"> {{ gpio.name }} </td> <td class="border"> {{ gpio.type }} </td> <td class="border"> {{ gpio.state }} </td> <td class="border"> {{ gpio.changed }} </td> </tr> {% endfor %}
步骤2:修改下拉菜单,添加筛选逻辑
替换原下拉菜单代码,添加JavaScript处理点击事件来筛选表格行:
<div class="dropdown"> <button class="btn btn-primary dropdown-toggle p-2" type="button" id="gpioDropdown" data-bs-toggle="dropdown" aria-expanded="false"> Select GPIO </button> <ul class="dropdown-menu" aria-labelledby="gpioDropdown"> <!-- 增加"显示全部"选项 --> <li><a class="dropdown-item" data-gpio="all">显示全部</a></li> {% for gpio in gpios %} <li><a class="dropdown-item" data-gpio="{{ gpio.gpio }}">{{ gpio.gpio }}</a></li> {% endfor %} </ul> </div> <script> // 给所有下拉选项绑定点击事件 document.querySelectorAll('.dropdown-item').forEach(item => { item.addEventListener('click', function() { const selectedGpio = this.getAttribute('data-gpio'); const tableRows = document.querySelectorAll('#gpios tr'); tableRows.forEach(row => { if (selectedGpio === 'all' || row.getAttribute('data-gpio') === selectedGpio) { row.style.display = ''; // 显示匹配行 } else { row.style.display = 'none'; // 隐藏不匹配行 } }); // 更新下拉按钮的显示文本 document.getElementById('gpioDropdown').textContent = this.textContent; }); }); </script>
方案二:HTMX风格后端筛选(推荐,符合无刷新理念)
如果数据量大或需要获取最新数据,通过HTMX请求后端接口,获取筛选后的表格内容替换原有tbody。
步骤1:修改FastAPI端点,添加筛选参数
假设你的后端基础端点如下,新增筛选逻辑和专用的表格内容接口:
from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") # 模拟GPIO数据,实际可从数据库读取 gpios_data = [ {"gpio": "GPIO1", "name": "LED", "type": "output", "state": "on", "changed": "2024-05-20"}, {"gpio": "GPIO2", "name": "Button", "type": "input", "state": "off", "changed": "2024-05-20"}, ] @app.get("/") async def root(request: Request, gpio: str = None): filtered_gpios = gpios_data if gpio and gpio != "all": filtered_gpios = [g for g in gpios_data if g["gpio"] == gpio] return templates.TemplateResponse("index.html", {"request": request, "gpios": filtered_gpios}) # 仅返回表格tbody内容的接口,提升HTMX请求效率 @app.get("/gpio-table") async def gpio_table(request: Request, gpio: str = None): filtered_gpios = gpios_data if gpio and gpio != "all": filtered_gpios = [g for g in gpios_data if g["gpio"] == gpio] return templates.TemplateResponse("components/gpio.html", {"request": request, "gpios": filtered_gpios})
步骤2:修改前端下拉菜单,添加HTMX属性
将HTMX属性绑定到每个下拉选项,实现无刷新更新表格:
<div class="dropdown"> <button class="btn btn-primary dropdown-toggle p-2" type="button" id="gpioDropdown" data-bs-toggle="dropdown" aria-expanded="false"> Select GPIO </button> <ul class="dropdown-menu" aria-labelledby="gpioDropdown"> <li> <a class="dropdown-item" hx-get="/gpio-table?gpio=all" hx-target="#gpios" hx-swap="innerHTML"> 显示全部 </a> </li> {% for gpio in gpios %} <li> <a class="dropdown-item" hx-get="/gpio-table?gpio={{ gpio.gpio }}" hx-target="#gpios" hx-swap="innerHTML"> {{ gpio.gpio }} </a> </li> {% endfor %} </ul> </div>
原代码问题说明
你之前的代码存在几个关键问题:
- HTMX属性错误绑定到了下拉按钮而非选项上,点击按钮无法触发筛选逻辑
hx-select="value"是无效配置,此属性用于从响应中提取特定内容,你场景下不需要hx-target="#test"指向的目标元素不存在,应改为表格tbody的#gpios- 用
<form>包裹下拉菜单无必要,HTMX可直接发送请求,无需表单提交
内容的提问来源于stack exchange,提问作者Nickodimus
相关产品推荐
相关产品推荐

