Creating UI Elements With HTMX

#
By Mike Davey, Senior Editor

HTMX is a JavaScript library that enables developers to perform AJAX requests, trigger CSS animations, and invoke WebSocket and server-side events directly from HTML elements. It is designed to remove a lot of the developer-managed JavaScript from the frontend by adding more properties to HTML. In this article, we’ll look into how to build simple UI elements with HTMX, examine how it works with WordPress, and see how you can start experimenting with HTMX right in your browser.

HTMX is designed to allow you to create dynamic, interactive elements with minimal code. It’s a relatively lightweight library, so it shouldn’t add a lot of overhead. However, calling it a library to begin with may be incorrect. If we define a tool by how it’s most often used, then HTMX is usually a framework.

The precise distinction between a library and a framework can get a bit blurry. Ultimately, whether HTMX is considered a library or a framework depends on how you define the terms and how you’re using it.

AJAX Requests in HTMX

The core of HTMX is a set of attributes that allow you to issue AJAX requests directly from HTML. Here’s how it works:

  1. Add the hx- prefix to an HTML element that you want to use to issue an AJAX request. For example, you might add hx-get to a button element to make a GET request, or hx-post to a form element to make a POST request. Other attributes include hx-put, hx-patch, and hx-delete.
  2. Specify the URL of the resource you want to request using one of these attributes.
  3. AJAX requests in HTMX default to triggering on the “natural” event for an element, i.e., change for input, submit for form, and so on. You can change this with the hx-trigger attribute.
  4. The element that issued the request includes its value by default. In the case of forms, the default is to include the values of all the form’s inputs. You can use the hx-params attribute to filter out parameters, or include the values of other elements with the hx-include attribute.

That’s the basic idea. You can find a more detailed explanation in the HTMX AJAX doc.

Using HTMX With WordPress

The documentation for HTMX is pretty solid, but it’s a relatively new technology, and there’s limited documentation and support available for using it specifically with WordPress. With that said, there are some projects on GitHub that might help get you started.

The first is htmxpress, a work-in-progress plugin for powering WordPress with HTMX. It uses the Rewrite Endpoints API to create a custom endpoint, with custom template logic, to allow dynamic server-side rendering.

The second is HTMX-API-WP, This plugin enables a new endpoint, /wp-htmx/v1/, from which you can load HTMX templates. While it’s not official, the author notes in the readme that he’s “…using this in production in a few projects and it’s working great, stable and ready to use,” with an additional note that it may still have some bugs.

Installing HTMX

There are several ways to install HTMX, depending on your specific needs and the type of project you’re working on.

  • Using npm: If you’re building a JavaScript application using npm, you can install HTMX by running the following command in your terminal:
npm install htmx.org

Using npm, you can also bundle HTMX with extensions and code specific to your application.

<script src="https://unpkg.com/[email protected]" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
  • Downloading: You can get a copy of htmx.min.js from UNPKG, add it to your project directory, and then include it with a <script> tag.
<script src="/path/to/htmx.min.js"></script>

The installation docs also include information for installing HTMX with Webpack.

HTMX Playground

We’re going to ignore all of that for now, and see what we can do in the HTMX Playground created by Lasse H. Bomholt.

It provides a simple and interactive environment where you can write and test HTMX code without setting up a full project. It includes a text editor, a preview window, and a console for debugging.

The welcome screen in HTMX Playground, with code editor on the left and output on the right.

The HTMX Playground starts you off with a basic example, a button that loads the name of a musical genre picked from a list. Clicking on Find examples… opens a dropdown menu that allows you to choose from Click To Edit, Click To Load, Infinite Scroll, Active Search, and Modal Dialog in Bootstrap. Intriguing possibilities, but I’m going to see what I can get just by modifying the basic example.

The code editor, located on the left, shows three tabs: server.js, index.html, and button.html. Clicking the eyeball icon in the code editor reveals two more tabs, .playground.json and .loader.html. The panel on the right shows the generated UI element.

Rather than musical genres, I want a button that will give users a random character from the Simpsons. Below is the original code from server.js:

let genres = [
    "Rock",
    "Electronic",
    "Country",
    "Heavy metal",
    "Hip hop",
    "Jazz",
    "Classical",
    "Soul",
    "Folk",
    "Reggae",
    "Techno",
    "Disco"
]

on.get("/", (request) => {

    let context = {
        text: "Click for a random music genre"
    }

    return render(request, 'index.html', context)
})

on.post("/random-genre", (request) => {

    let genre = genres[Math.floor(Math.random() * genres.length)]

    let context = {
        text: genre
    }

    return render(request, 'button.html', context)
})

Making a few modifications will get it to start spitting out Simpsons characters. I’ve updated the initial let genre = [ and let genre = genre statements to let simpsons = [ and let genre = simpsons, but that’s not actually necessary. All I really needed to do was change text entries:


let simpsons = [ "Chief Wiggum", "Seymour Skinner", "Cookie Kwan", "Lindsay Nagle", "Mayor Quimby", "Patty and/or Selma", "Sherri and/or Terri", "Dolph", "Jimbo Jones", "Sarcastic Middle-Aged Man", "Squeaky Voiced Teen", "MIIILLLLLHHHOOOOUUUUSE!" ] on.get("/", (request) => { let context = { text: "Click for a random Simpsons character!" } return render(request, 'index.html', context) }) on.post("/random-genre", (request) => { let genre = simpsons[Math.floor(Math.random() * simpsons.length)] let context = { text: genre } return render(request, 'button.html', context) })

You may have noticed I didn’t change every instance of genre to simpsons. For example, on.post("/random-genre" and let genre = simpsons need to retain it or the button will stop working. To make these changes, I’ll need to make alterations to the button.html file. Here’s the original:

<button hx-post="/random-genre" hx-swap="outerHTML">
    <b>
        {{ text }}
    </b>
</button>

The HTML button element has two HTMX attributes: hx-post and hx-swap.

The hx-post attribute specifies that the button should make a POST request to the URL /random-genre when it is clicked. The hx-swap attribute specifies outerHTML, which replaces the entire target element with the response. The {{ text }} placeholder is used to display the text that is returned by the server in the response.

The first step is to change the URL in the hx-post attribute to a different endpoint, in this case /random-simpson. Next, I’ll update the endpoint in server.js to use /random-simpson as well.

<button hx-post="/random-simpson" hx-swap="outerHTML">
    <b>
        {{ text }}
    </b>
</button>

Finally, I’ll modify index.html to replace the current messaging, and change the stylesheet it’s calling to one that doesn’t force a dark theme, but switches to it if the user has it set as a system-wide preference on their device. I’ll also change the H1 to something more descriptive at the same time.

<html>
<head>
    <link href="https://unpkg.com/[email protected]/out/water.css" rel="stylesheet">
    <script src="https://unpkg.com/htmx.org@<2/dist/htmx.js" defer></script>
</head>
<body>

    <h1>Random Simpsons Characters</h1>

    {% include 'button.html' %}

    <p>
        "Stop thinking about TV and get back to work." - Marge Simpson 
    </p>
</body>
</html>

Sharing Your UI Element

To share the elements you create in HTMX Playground, click Copy as JSON, and then paste the output into a Gist and get the raw URL. Next, click Load Playground and enter the raw URL. The URL on the HTMX Playground will update, allowing you to share your element.

Wrapping Up

HTMX can be used to build very complex elements. Although I restricted myself to a very simple example here, there’s much further you could go just with HTMX Playground. In particular, the Active Search example has rich possibilities.

Have you experimented with HTMX, or used it in a project? What was your experience like? Let us know in the comments below.

About the Author

Mike Davey Senior Editor

Mike is an editor and writer based in Hamilton, Ontario, with an extensive background in business-to-business communications and marketing. His hobbies include reading, writing, and wrangling his four children.