Created
November 21, 2023 19:51
-
-
Save DurandA/41b49dc1e1d95689af338b4e2e4376e4 to your computer and use it in GitHub Desktop.
HTMX demo with dynamic filters and infinite scroll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from fastapi import FastAPI, Request | |
from fastapi.responses import HTMLResponse | |
from fastapi.staticfiles import StaticFiles | |
import random | |
import asyncio | |
app = FastAPI() | |
app.mount("/static", StaticFiles(directory="static"), name="static") | |
@app.get("/", response_class=HTMLResponse) | |
async def read_root(): | |
return """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>HTMX Demo</title> | |
<script src="https://unpkg.com/[email protected]" integrity="sha384-rgjA7mptc2ETQqXoYC3/zJvkU7K/aP44Y+z7xQuJiVnB/422P/Ak+F/AqFR7E4Wr" crossorigin="anonymous"></script> | |
</head> | |
<body> | |
<h1>Dynamic Filters with Infinite Scroll</h1> | |
<form action="/filter" method="get" hx-boost="true" hx-target="#results" hx-replace-url="false"> | |
<select name="category"> | |
<option value="">Select Category</option> | |
<option value="Category1">Category 1</option> | |
<option value="Category2">Category 2</option> | |
</select> | |
<select name="color"> | |
<option value="">Select Color</option> | |
<option value="Red">Red</option> | |
<option value="Blue">Blue</option> | |
</select> | |
<input type="submit" value="Filter"> | |
</form> | |
<ul id="results"> | |
<!-- Filtered results will appear here --> | |
</ul> | |
<img id="indicator"class="htmx-indicator" width="60" src="/static/bars.svg"> | |
</body> | |
</html> | |
""" | |
def generate_fake_data(page: int, category: str, color: str): | |
return [{"name": f"Item {i}", "category": category or f"Category{i % 3 + 1}", "color": color or random.choice(["Red", "Blue", "Green"])} for i in range(page * 10, (page + 1) * 10)] | |
@app.get("/filter", response_class=HTMLResponse) | |
async def filter(request: Request, category: str = "", color: str = "", page: int = 0): | |
await asyncio.sleep(0.5) | |
filtered_data = generate_fake_data(page, category, color) | |
next_page = page + 1 | |
hx_load_more_attrs = f""" | |
hx-get="/filter?page={next_page}&category={category}&color={color}" | |
hx-target="#results" | |
hx-swap="beforeend" | |
hx-trigger="revealed" | |
hx-indicator="#indicator" | |
""" | |
return ''.join( | |
f""" | |
<li {hx_load_more_attrs if item == filtered_data[-1] else ""}> | |
{item["name"]} - {item["category"]} - {item["color"]} | |
</li> | |
""" | |
for item in filtered_data | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment