Using FastHTML, I would like to create a navigation bar that updates a div's content based on the item clicked.
I wrote the following piece of code, but nothing happens when I click the buttons: the #page-content
div doesn't update, and I don't see the logs of the GET methods being triggered.
from fasthtml.common import *
app = FastHTML()
@app.route("/", methods=["get"])
def index():
return Html(
Body(
Header(navigation_bar(["page1", "page2"])),
Div(page1(), id="page-content"),
),
)
def navigation_bar(navigation_items: list[str]):
return Nav(
Ul(
*[
Li(Button(item, hx_get=f"/{item}", hx_target="#page-content"))
for item in navigation_items
]
),
)
@app.route("/page1", methods=["get"])
def page1():
return Div("You are on page 1.")
@app.route("/page2", methods=["get"])
def page2():
return Div("You are on page 2.")
serve()
Here is the generated HTML:
<html>
<head></head>
<body>
<header>
<nav>
<ul>
<li>
<button hx-get="/page1" hx-target="#page-content">page-1</button>
</li>
<li>
<button hx-get="/page2" hx-target="#page-content">page-2</button>
</li>
</ul>
</nav>
</header>
<div id="page-content"><div>You are on page 1.</div></div>
</body>
</html>
I think the HTML is generated correctly, as the tags' attributes related to HTMX look like what I could see on online examples. Where could the issue be?
The issue came from the fact that I was wrapping my Body
component into an Html
component manually. Removing the Html
component, FastHTML takes care of the wrapping automatically and also includes the required scripts.
Here is my updated piece of code:
from fasthtml.common import *
app = FastHTML()
@app.route("/", methods=["get"])
def index():
return Body(
Header(navigation_bar(["page1", "page2"])),
Div(page1(), id="page-content"),
)
def navigation_bar(navigation_items: list[str]):
return Nav(
Ul(
*[
Li(Button(item, hx_get=f"/{item}", hx_target="#page-content"))
for item in navigation_items
]
),
)
@app.route("/page1", methods=["get"])
def page1():
return Div("You are on page 1.")
@app.route("/page2", methods=["get"])
def page2():
return Div("You are on page 2.")
serve()