Practice makes perfect

As of right now I feel pretty proficient building tools with htmx

  • pairing with v.0 is amazing: example















The following examples
















The URL

The current URL can be controlled via htmx. This can be great, but it can also lead into some funny locations.



Lets say we created a contacts page and we wanted to allow deleting from the contacts page. What should happen?
















First the HTML for the delete button

<button hx-delete="/contacts/{{ contact.Id }}"
      hx-indicator="#delete-indicator"
      hx-push-url="true"
      hx-target="body">
Delete Contact
</button>















Disable the button

This takes advantage of more HTMX events and a touch of javascript. Events can be observered by using htmx.logAll(). This will spam the console with all the events that htmx processes and emits

export function disableButton(button: HTMLButtonElement) {
    if (!button) {
        throw new Error("form without button");
    }

    button.removeAttribute("disabled", true);
    button.addEventListener("htmx:beforeRequest", function() {
        button.toggleAttribute("disabled", true);
    })

    button.addEventListener("htmx:beforeSwap", function() {
        button.toggleAttribute("disabled", true);
    })
}















DELETE

How do we get back to the contacts page? How does this work?
















Introducing 303

Wait... I thought it was 302.



302 302



303 303
















DELETEing from inline contacts vs from page?

You could imagine that we have a page for each contact in our application that could have a delete button.



We need a way to tell the backend to redirect instead of NoContent response.



<button hx-delete="/contacts/{{ contact.Id }}?redirect=true"
      hx-indicator="#delete-indicator"
      hx-push-url="true"
      hx-target="body">
Delete Contact
</button>

The ?redirect=true allows us to encode within the url the behavior we want. Remember, URLs can be state containers that have intention behind them, use it
















To The Next Problem!
















Too many contacts

Lets say that we had thousands of contacts, we would not want to send them all down at once. How can we accomplish this with htmx?



hx-trigger

Non-standard Events

There are some additional non-standard events that htmx supports:

  • load - triggered on load (useful for lazy-loading something)
  • revealed - triggered when an element is scrolled into the viewport (also useful for lazy-loading). If you are using overflow in css like overflow-y: scroll you should use intersect once instead of revealed.
  • intersect - fires once when an element first intersects the viewport. This supports two additional options:
    • root: - a CSS selector of the root element for intersection
    • threshold: - a floating point number between 0.0 and 1.0, indicating what amount of intersection to fire the event on


views/blocks.html

{{ block "blocks" . }}
    {{ range .Blocks }}
        <div style="background-color: #eee; margin: 2px">
            <span>{{ .Id }}</span>
        </div>
    {{ end }}

    {{ if .More }}
        <div hx-trigger="revealed" hx-swap="outerHTML" hx-get="/blocks?start={{ .Next }}"></div>
    {{ end }}
{{ end }}


Contacts are similar

The contacts are similar in the sense that we may not be able to see them all so a request for more is easily achieved with htmx
















Filtering?

Well filtering is a subset of the previous problem. Like any list that is too large you wont have all the data so when you do a filtering it will require a server side call.



This pattern is known as the Active Search pattern on the htmx in action book.

<form action="/contacts" method="get" class="tool-bar">
    <label for="search">Search Term</label>
    <input id="search" type="search" name="q" value="{{ request.args.get('q') or '' }}" (1)
           hx-get="/contacts" (2)
           hx-trigger="search, keyup delay:200ms changed"/> (3)
    <input type="submit" value="Search"/>
</form>















An Observation

In some sense, htmx returns to more of an "engineering" feel.
















There is much much more you can do

The question you should be asking yourself is "how much of my state can be represented by a url + http codes?"



The answer is a shocking amount of it can be. There are few applications that cannot be and those are enumerated at the front of the htmx book. But here is one of my own.



  • conways game of life
  • spreadsheets
  • maps















Like and Subscribe

Hey... like and sub to my yt channel :)


ThePrimeagen

  • produced videos. been on a break for 3 months from this one, planning the comeback

ThePrimeTimeagen

  • memes, articles, and YT video tech reaction content.

TheVimeagen

  • Long form programming content

ThePrimeagen on Twitch

  • Where all the YT channels get their content from

ThePrimeagen on Twitter

  • lots of shoot posting