HTMX client side routing?
Asked Answered
G

4

6

Let's say my user needs to be able to get back to a certain location in the app. For example we'll say a tab. The htmx attribute hx-push-url allows me to update the URL in the bar when they click the tab. For example we could push '/tab3' to the url bar.

Let's say the user copied the location into an email and sent it to their friend. The friend copies it into their browser and hits enter. What do they see? How does it get that way?

I see in the documentation it says:

"NOTE: If you push a URL into the history, you must be able to navigate to that URL and get a full page back! ... Additionally, htmx will need the entire page when restoring history if the page is not in the history cache."

https://htmx.org/docs/#history

What's the best-practice way to "get a full page back" on an htmx project? Assuming there's something like Django or Flask on the back-end, I can certainly render the whole page with the correct tab having the "active" class and the content area with the correct content. But this seems duplicative, no? If it were a React/Vue project it would be possible to use the built-in routing facilities to render the page client side, correct? But what about on an htmx project?

If it's not possible for htmx to do this client side routing and rendering, it seems like the most prudent approach to development might be to build everything without any Ajax behavior first, to confirm that all of the server side routing and rendering works correctly, and then add htmx sugar on top of that. Does this make sense as an approach or is there an established better way to do this?

Gerigerianna answered 26/5, 2023 at 16:14 Comment(1)
Can the title of this be changed? In truth this question has nothing to do with client side routing, and instead is a question related to expected behavior of HTMX projects. When I googled 'HTML client side routing' this page comes up, and is irrelevant.Crossexamine
C
5

HTMX is a thin communication layer over your backend, it does not have client side routing or rendering, because your backend has these features. So yes, you have to make sure that every endpoint works without HTMX, since HTMX will just load these endpoints. It's not duplicative because you only have to do this once on the backend (you have no frontend code like with React/Vue).

Usually on a backend endpoint you want to support both partial- and full page rendering. When a request comes from HTMX it will have the HX-Request header set to true, so you know on the backend that the user asked for only the partial content of the page. On the other hand if the request does not have this header, then the user asked for the full page content. This is a basic task when working with Django+HTMX, you can use the dynamic base template technique for this.

Callista answered 29/5, 2023 at 9:23 Comment(1)
That dynamic base template technique page is a good example. I understand now how it can be done without being duplicative. I was imagining having to make a bunch of separate views for the partials. Not so! ThanksGerigerianna
C
0

the best answer i've found for django/flask peeps is the following pattern alongside django-htmx's middleware:

 def home(request: HttpRequest) -> HttpResponse:
        if request.htmx:
            template = "home/partials/home.html"
        else:
            template = "home/home.html"

then in your template structure follows the following pattern:

<!--base.html -->
<body>
    <nav>
        navbar
    </nav
<div id="main-container">
{% block content %}
{% endblock content %}
</div>
</body>

<!-- home/home.html -->
{% extends base.html %}
{% block content %}
   {% include 'home/partials/home.html' %}
{% endblock content %}

<!-- home/partials/home.html -->
<div>
    home page
</div>




file structure:
templates/
---------home/
-------------home.html
-------------partials/
----------------------home.html

this gives you a full page render when you share the link etc, but allows you to have single page navigation/partial renders that target the "#main-container". If use hx-push-url, then you have a full page or partial render method for any htmx page and url.

there are other ways, some with less code etc, but this method is structured like the Next.js app router and keeps apps with many pages manageable.

Churning answered 2/8, 2023 at 0:38 Comment(0)
A
0

Language independend pseudocode:

page_endpoint:
  if header:HX-Request
     generate and return page partial for header:HX-Current-URL
  else
     generate and return root

In the "generate and return root" case, once received by the browser, HTMX will recurse down your root element to generate the full HTML document using hx-get. At some point in that recursion, it'll call the page_endpoint again with the HX-Request header, and you'll respond with just the page partial content.

Note that page_endpoint knows what page partial to return because it gets the HX-Current-URL header.

Arbitress answered 18/11, 2023 at 19:9 Comment(0)
C
0

You can implement client-side-routing on htmx by doing the following:

  1. On your backend, returning the page layout if the hx-request http header does not exist in the request.
  2. On your frontend anchor links, replace the href attributes with hx-get and set hx-push-url=true.

Check this post for a working example: https://paulallies.medium.com/htmx-page-navigation-07b54742d251

Cleodel answered 4/2 at 8:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.