Skip to content

Instantly share code, notes, and snippets.

@DurandA
Created November 21, 2023 19:51
Show Gist options
  • Save DurandA/41b49dc1e1d95689af338b4e2e4376e4 to your computer and use it in GitHub Desktop.
Save DurandA/41b49dc1e1d95689af338b4e2e4376e4 to your computer and use it in GitHub Desktop.
HTMX demo with dynamic filters and infinite scroll
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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