Going deeper with htmx 4 — combining htmx and JavaScript

InfoWorld ·

Going deeper with htmx 4 — combining htmx and JavaScript

htmx lets you add rich functionality to web pages without writing JavaScript . But it also lets you integrate JavaScript if you need it, either by adding functions in-line to elements or by writing more complex hooks for events. These behaviors let you take web pages that already use JavaScript, and either migrate to htmx entirely or add htmx only where it’s needed — for instance, in new parts of an application. Generally, htmx works best with green-field applications, since you can start with a non-interactive page and just layer in the behaviors you want as they’re needed. But htmx can also work as an add-on for a page that already uses JavaScript, or as a migration target away from existing JavaScript. Using htmx with JavaScript When you want to integrate htmx with hand-rolled JavaScript, htmx offers you several ways to do it. Some are extremely basic, but tightly coupled to the objects they work with. Others are more advanced and flexible, but require more work to use. Using hx-on attributes A basic way to add JavaScript behaviors to objects is through a very htmx-like mechanism, the hx-on attributes. Add one of these to a given object and you can provide code or function calls inline. For example: Click here to log to the console The inline code can be a whole code block, as shown here, or a function call to your own code. One advantage of using hx-on is consistency with other hx- attributes. If all your existing interaction is powered by htmx, adding more hx- attributes for custom functionality keeps things uniform. On the other hand, if you want your custom functionality to be mechanically distinct from htmx, consider the approach discussed next: registering callbacks. Using the htmx API The more complex way to “wire up” JavaScript functionality for htmx-enabled pages is to use the htmx object and its methods. With htmx you can register callback functions for any behavior. The htmx object provides a set of interfaces for triggering htmx behaviors on objects in the DOM. Three of the most commonly used interfaces: htmx.on() adds an event listener to an object, in much the same manner as the hx-on attribute does. The main difference is that adding an inline attribute typically requires changing how you render the object (e.g., from a server-side template). htmx.onLoad() registers a callback to run whenever new content is added to the DOM by htmx, after htmx has already processed it. This way, content loaded dynamically via a fetch action can be wired up in some custom way. Normally, anything loaded by htmx that contains hx- attributes will automatically be wired up, but this allows you to do that for “plain” content with no hx- attributes. htmx.ajax() issues a custom htmx request, the results of which are processed by htmx and inserted into the DOM. All the behaviors htmx exposes through attributes can be triggered manually though the API. So, if you wanted to, you could skip wiring up objects by adding hx- attributes, and instead use the API via your own JavaScript code. To some degree this defeats the purpose of htmx. But there may be cases where you will want to start using htmx without annotating objects, at least at first (for instance, to avoid making immediate changes to your HTML templates). Using hx-live and the q() function htmx 4 introduced a new feature called hx-live , which allows you to select objects using a query function, q() , and perform operations on them using a syntax similar to that used for hx- attributes. You can think of q() as a less verbose way to run document.querySelector() on the current page, then work with the returned objects. Most of what you would do with q() involves DOM manipulations where the behavior of one object affects many others. For instance: Select all Clicking the button would locate every element on the page with the class item and toggle the presence of the class selected on that element. q() exposes a few other methods in the same vein: take() removes a class or attribute from selected elements, then adds them to the element making the call. It’s a convenient way to perform an action on everything but the given element (e.g., all other buttons in a div but this one). trigger() dispatches a given event to everything matching the query. It includes options for keeping the event from bubbling if needed. insert() adds HTML within or around selected items. What’s important about q() is that you can use it entirely outside of htmx attibutes, as part of your own custom-written JavaScript functions or callbacks. You could even begin adding htmx functionality to a page by using only q() and its behaviors, hand-in-hand with JavaScript, then build outwards from that to replace a site’s legacy functionality with htmx over time. Using htmx with Alpine.js As a rule, front-end web frameworks shouldn’t be mixed, the better to minimize side effects and unpredictable behaviors. If you use htmx to add reactive behaviors to a page, you will get the best results if htmx (and whatever JavaScript you integrate with it) is the only source of reactive behavior. Still, htmx makes provisions for working hand-in-hand with other ways to add reactivity. Aside from hand-written JavaScript, you can integrate the Alpine.js library . Alpine.js is a JavaScript library with a similar philosophy to htmx. WIth Alpine, you can add behavior to elements in a web page by adding special attributes that begin with x- . For instance, x-on:click would add some behavior to an element when clicked. It isn’t hard to see how this behavior could conflict with htmx, or vice versa. But htmx comes with an extension, hx-alpine-compat , that ensures Alpine behaviors are consistently enabled and kept active in components handled by htmx. InfoWorld’s Matt Tyson has explored in detail how htmx and Alpine.js can complement each other . Using htmx with server-side libraries Back-end web frameworks are by definition front-end agnostic. You don’t tend to see a web framework favor, say, Boostrap or Alpine.js, because that just limits the potential audience and creates unnecessarily tight couplings between front end and back end. But some web frameworks do offer supplementary support for specific front ends, including htmx. Django and FastAPI have third-party libraries that provide convenience features for developers building HTMX-powered front-ends. Jinja2, the templating language used with many back-end frameworks, has a third-party extension called Jinja2 Fragments that makes it easier to render templates in part so only the relevant bits can be supplied for an htmx fetch operation. One of the more recent Python web frameworks, Litestar , has native htmx support . This allows you to render htmx-specific templates that are automatically populated with htmx-specific attributes such as target elements or event names. The big appeal of htmx is how it sidesteps the inherent complexities of JavaScript . It gives you the vast majority of the interactive functionality you need for a web page by way of declarative HTML syntax. At the same time, htmx leaves the door open for JavaScript integration, for working hand-in-hand with Alpine.js, and for web frameworks that elect to work more closely with htmx’s simplified approach.

Источник: InfoWorld