AnswerDotAI / FastHTML-Gallery

https://gallery.fastht.ml/
65 stars 10 forks source link

Tracking current path and propagating it to child components #42

Closed callmephilip closed 2 months ago

callmephilip commented 2 months ago

I am wondering if you have found a cleaner way of doing this (sharing my approach below). Parts of the component tree might need access to request context (path in this case) - how do you get access to this data without needing to propagate attributes all the way down?

from fasthtml.common import *

app,rt = fast_app(live=true)

def AppLayout(content: FT, current_path: str):
    nav_links = [
        {"name": "Home", "href": "/"},
        {"name": "About", "href": "/about"},
        {"name": "Contact Us", "href": "/contact"},
    ]
    return Div(
        Nav(
            Ul(
                *[Li(A(nl["name"] + ("✅" if current_path == nl["href"] else ""), href=nl["href"])) for nl in nav_links]
            )
        ),
        Hr(),
        content
    )

@rt('/')
def get(request): return AppLayout(content=Div("Home"), current_path=request.url.path)

@rt('/about')
def get(request): return AppLayout(content=Div("About"), current_path=request.url.path)

@rt('/contact')
def get(request): return AppLayout(content=Div("Contact us"), current_path=request.url.path)

serve()
Isaac-Flath commented 2 months ago

I don't know of a better way.

However, on a completely separate note, I was playing with this example, and some routing stuff may interest you (it's what I hope to do in the future). Notice how I don't define any route strings and pass around Python functions and not route strings and fasthtml just takes care of it for you!

from fasthtml.common import *

app,rt = fast_app(live=true)

# *c is nice for making easier to use functions
def AppLayout(*c, req):
    # Notice that nav_links is not a route string!
    nav_links = (('Home',index),('About',about),('Contact',contact))
    return Container(
        # notice that the routes are created by stringfying the ojbects defined below (ie `index`)
        Nav(Ul(*[Li(A(f"{n}{' ✅' if req.url.path==str(r) else ''}",href=r)) for n,r in nav_links])),
        Hr(),
        # Anything you passed goes here, just like the OOTB components like `Div`
        *c)

#@app.get - I prefer this style so I can easily match get with hx_get for htmx
# But will use @rt to explore all the stuff FastHTML can do for me

# Notice how there is no route string anywhere
@rt # Most concise and defaults to creating both a get and a post for this route
def index(req): return AppLayout(H1("Home"),P('Some text'), req=req)

@rt
def about(req): return AppLayout(H1("About"),Button('Broken Button'), req=req)

@rt
def contact(req): return AppLayout(H1("Contact us"), req=req)

serve()