Skip to content

Instantly share code, notes, and snippets.

@DurandA
Created November 21, 2023 19:51
Show Gist options
  • Select an option

  • Save DurandA/41b49dc1e1d95689af338b4e2e4376e4 to your computer and use it in GitHub Desktop.

Select an option

Save DurandA/41b49dc1e1d95689af338b4e2e4376e4 to your computer and use it in GitHub Desktop.

Revisions

  1. DurandA created this gist Nov 21, 2023.
    52 changes: 52 additions & 0 deletions bars.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    68 changes: 68 additions & 0 deletions main.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    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
    )