

How to Integrate HTMX and Shoelace Web Components
source link: https://khalidabuhakmeh.com/how-to-integrate-htmx-and-shoelace-web-components
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How to Integrate HTMX and Shoelace Web Components

In my last post, Shoelace Web Components with ASP.NET Core, I showed ASP.NET Core developers how to integrate the web components of Shoelace into an existing web application. It’s incredible, and you should check it out. If you’ve read this blog any time, you might have read a post or two about HTMX, a library for building dynamic and maintainable web experiences; I love it.
While the two libraries can work together, there’s an issue you need to work around to get the advantages of both. In this post, we’ll discuss the issues with using Shoelace with HTMX and how to get it working again with your ASP.NET Core applications. If you’re using any other technology stack (Django, Spring, or Next.js), don’t worry; the solution here will work for you, too.
Shoelace, the Shadow DOM, and HTMX
Shoelace is a web component library that encapsulates all functionality in a user-friendly HTML tag. Let’s take a look at the most common element, the Button.
After installing the Shoelace scripts, adding the sl-button
element in HTML markup is straightforward.
<sl-button>Button</sl-button>
The abstraction works out nicely from a developer and user perspective, as these elements “just work” with HTML (as you might have read in the post mentioned earlier). Looking at how a client renders this element shows some of the implementation details.
<sl-button variant="default" size="medium" data-optional="" data-valid="">
#shadow-root (open)
<button part="base" class=" button button--default button--medium button--standard button--has-label " type="button"
title="" name="" value="" role="button" aria-disabled="false" tabindex="0">
<slot name="prefix" part="prefix" class="button__prefix"></slot>
<slot part="label" class="button__label"></slot>
<slot name="suffix" part="suffix" class="button__suffix"></slot>
<!--?lit$16265820754$-->
<!--?lit$16265820754$-->
</button>
Button
</sl-button>
Shoelace uses the Lit library to build components utilizing the Shadow DOM. These elements exist virtually in the DOM and are part of the page but may or may not be accessible based on the implementation.
As you likely guessed, HTMX doesn’t look at the Shadow DOM of custom web components to find common elements such
as button
, input
, or select
. This can be a problem for folks using HTMX to hijack form
elements or adding hx-
attributes to shoelace components. These custom components aren’t added to the ultimate request that HTMX builds.
Don’t worry; there’s an easy fix.
HTMX Events To The Rescue
HTMX has many events that allow you to intercept context at any point in the process.
For our use case, we want to intercept all outgoing requests and determine if our target
element and any of its
children contain Shoelace components.
Luckily for us, Shoelace components follow a typical pattern of having name
and value
attributes. We can assume that
any element with a name
attribute is expected to be transmitted in a request.
Let’s hook into the htmx:beforeRequest
. Add the following code into any script file that loads after HTMX and Shoelace
libraries.
document.body.addEventListener('htmx:beforeRequest', evt => {
const elements = [
evt.target,
...evt.target.querySelectorAll('*')
];
for (const el of elements) {
const {tagName, name, value, disabled, checked} = el;
// ignore inputs that aren't from shoelace
if (!tagName.startsWith("SL-")) continue;
// all inputs can be disabled
if (disabled) continue;
// the name is required
if (name === undefined || name === "") continue;
if (value === undefined) continue;
// a checkable element
if (checked !== undefined) {
if (checked) {
evt.detail.requestConfig.parameters[name] = value;
}
} else {
// it is a simple element
evt.detail.requestConfig.parameters[name] = value;
}
}
});
Note that form values can have duplicate names within a form collection. I don’t commonly duplicate names, but it might be a typical pattern for arrays in other technology stacks. If so, you may need to alter the code above to suit your needs.
As an additional note, there may be some components you need to account for in your server code. For
example, sl-select
component works with arrays.
The current value of the select, submitted as a name/value pair with form data. When
multiple
is enabled, the value attribute will be a space-delimited list of values based on the options selected, and the value property will be an array. For this reason, values must not contain spaces. –Shoelace Documentation
So far, in my testing, this code works with most of the shoelace elements in the official documentation. That said, please test and modify the code according to your needs.
Conclusion
It’s always fun when things work together, but it’s not always the case. Luckily, both HTMX and Shoelace offer great APIs that allow you to smooth out some of these issues. Please try these two libraries in your ASP.NET Core applications and let me know how it goes.
As always, thanks for reading the posts, and I hope I helped you get on your way to a productive day. Cheers.
*Special thanks to Mario Hamann and his excellent post integrating Web Components and Livewire.
Tags: htmx javascript aspnet

About Khalid Abuhakmeh
Khalid is a developer advocate at JetBrains focusing on .NET technologies and tooling.
Recommend
-
8
Granny Knot Info Do your shoelaces sit crooked? Do you retie your shoes several times a day? These are both signs of a Granny Knot
-
14
Sutil.Generator This is a Shoelace and Fast wrapper generator for Sutil heavily inspider i...
-
7
Sutil.Shoelace 2.0.0-beta.43.1 Sutil bindings for Shoelace Web Components the contents of this package are auto-gen...
-
31
Jared White Posted on Dec 17...
-
7
Aocheng Yang April 8, 2022 11 minute read Exp...
-
5
Web componentsReactive web-componentsHow to create reactive web components with LemonadeJS There are two necessary methods to create reactive web-components using LemonadeJS. The method render() should return...
-
10
Brought to you by Carson Gross (creator of htmx) & Alex Russell (Mr. Web Platform 3000) join Amal for an EPIC discussion on web architectures, the evolution of rendering patterns & the...
-
6
January 23, 2024 How To Use Blazor Server-Rendered Components with HTMX
-
6
February 27, 2024 Shoelace Web Components with ASP.NET Core ...
-
8
shoelace and viteAdding shoelace asssets to vite: npm i @shoelace-style/shoelace vite-plugin-static-copy viteAdd "type": "module" into pack...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK