Skip to content

Commit abd1628

Browse files
committed
fix htmx article Nathan
1 parent bbfb9a1 commit abd1628

1 file changed

Lines changed: 69 additions & 32 deletions

File tree

src/articles/20260608-htmx.mdx

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ author: Nathan Perdijk
44
publishedAt: 2026-06-08
55
---
66

7-
# HTMX: Reactive Frontend from the Backend
8-
97
It's a scene that will be familiar to everyone:
108

119
An application for internal use, with a solid backend doing the heavy lifting and a frontend that… exists… Because there has to be some kind of user interface and it would be nice if it were somewhat "reactive."
@@ -22,9 +20,9 @@ With HTMX, a bit of knowledge of HTML and some CSS, you can actually just do it
2220

2321
# Look Mom, No JavaScript!
2422

25-
Well, almost. To get HTMX up and running you need exactly one JavaScript dependency, namely HTMX itself. (Oops, already caught in a tiny little lie.) But without any self-written JavaScript, so close enough! To use it, you can embed it as a script in your served HTML code (see Listing 1). The library is then served to the browser via a Content Delivery Network (CDN for the initiated), allowing the HTMX tags in your HTML code to do their job.
23+
Well, almost. To get HTMX up and running you need exactly one JavaScript dependency, namely HTMX itself. (Oops, already caught in a tiny little lie.) But without any self-written JavaScript, so close enough! To use it, you can embed it as a script in your served HTML code (see <a id="ref-listing-1"></a>[Listing 1](#listing-1)). The library is then served to the browser via a Content Delivery Network (CDN for the initiated), allowing the HTMX tags in your HTML code to do their job.
2624

27-
However, there are objections to using a CDN regarding privacy, security, and the functioning of your website when other parts of the internet go down. It is therefore better to simply include your own copy in your project, by downloading it [footnote 1] and making it available via your application server. In a SpringBoot project, for example, you only need to place the file in `/resources/static/htmx.js` and it will automatically be loaded from your own application server when you reference it in your HTML (see Listing 2). Great, now that we've done that, we have the power of all kinds of handy frontend tricks at our Backend fingertips. By adding a few simple attributes to our HTML and defining smart endpoints in the Backend, we can go all out.
25+
However, there are objections to using a CDN regarding privacy, security, and the functioning of your website when other parts of the internet go down. It is therefore better to simply include your own copy in your project, by [downloading it](https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js) and making it available via your application server. In a SpringBoot project, for example, you only need to place the file in `/resources/static/htmx.js` and it will automatically be loaded from your own application server when you reference it in your HTML (see <a id="ref-listing-2"></a>[Listing 2](#listing-2)). Great, now that we've done that, we have the power of all kinds of handy frontend tricks at our Backend fingertips. By adding a few simple attributes to our HTML and defining smart endpoints in the Backend, we can go all out.
2826

2927
# From JSON to HTML
3028

@@ -47,15 +45,15 @@ some annoyances from current web applications: JSON can go straight into the tra
4745

4846
# The Toolbox
4947

50-
As mentioned, HTMX provides attributes that you can include in your HTML, allowing it to interact with the Backend and with other parts of your HTML. The five attributes `hx-get`, `hx-post`, `hx-put`, `hx-patch`, and `hx-delete` will, when activated, send the corresponding GET/POST/PUT/PATCH or DELETE request to the specified endpoint. By adding an `hx-trigger` attribute, you can determine under which circumstances the request is actually sent — for example, in the case of a `mouseenter`, a `click`, or your own custom-defined events. You can also configure a polling mechanism via triggers, or combine multiple triggers. In Listing 3a, for example, a POST request is sent to the endpoint `/clickbait-clicked` when the button is clicked. For more information about triggers, see Footnote 2. The called endpoint naturally returns an HTML response as well. In your HTML, you can define what HTMX should do with that new HTML.
48+
As mentioned, HTMX provides attributes that you can include in your HTML, allowing it to interact with the Backend and with other parts of your HTML. The five attributes `hx-get`, `hx-post`, `hx-put`, `hx-patch`, and `hx-delete` will, when activated, send the corresponding GET/POST/PUT/PATCH or DELETE request to the specified endpoint. By adding an `hx-trigger` attribute, you can determine under which circumstances the request is actually sent — for example, in the case of a `mouseenter`, a `click`, or your own custom-defined events. You can also configure a polling mechanism via triggers, or combine multiple triggers. In <a id="ref-listing-3a"></a>[Listing 3a](#listing-3a), for example, a POST request is sent to the endpoint `/clickbait-clicked` when the button is clicked. For more information about triggers, see [the HTMX documentation on triggers](https://htmx.org/attributes/hx-trigger/). The called endpoint naturally returns an HTML response as well. In your HTML, you can define what HTMX should do with that new HTML.
5149

5250
# Such an Easy hx-target
5351

54-
If you don't provide HTMX with a target, HTMX uses the content of the HTML element that sent the request as the target for the new HTML. In Listing 3a, the text on the button will therefore be replaced by the HTML returned from the Backend (Listing 3b). But often on your web page, you want changes to happen elsewhere upon user interaction. If you have another piece of HTML on your web page in mind, you can fortunately tell HTMX that it has a different target, by adding `hx-target="#name-of-html-anchor-elsewhere"`. In that case, the HTML element with that anchor as its attribute becomes the target of your request. But a target alone is not enough — depending on what you want to happen, you may want to replace the content of the targeted HTML, or rather the surrounding HTML, or insert HTML above or below the target, or delete it… It's all possible — see the table in Listing 4, borrowed directly from the HTMX documentation itself (Footnote 3). For another practical example, see Listing 5, where clicking a button in a table with anchor "inner-outer-table" adds an extra row to the end of that table.
52+
If you don't provide HTMX with a target, HTMX uses the content of the HTML element that sent the request as the target for the new HTML. In [Listing 3a](#listing-3a), the text on the button will therefore be replaced by the HTML returned from the Backend (<a id="ref-listing-3b"></a>[Listing 3b](#listing-3b)). But often on your web page, you want changes to happen elsewhere upon user interaction. If you have another piece of HTML on your web page in mind, you can fortunately tell HTMX that it has a different target, by adding `hx-target="#name-of-html-anchor-elsewhere"`. In that case, the HTML element with that anchor as its attribute becomes the target of your request. But a target alone is not enough — depending on what you want to happen, you may want to replace the content of the targeted HTML, or rather the surrounding HTML, or insert HTML above or below the target, or delete it… It's all possible — see the table in <a id="ref-listing-4"></a>[Listing 4](#listing-4), borrowed directly from [the HTMX documentation itself](https://htmx.org/docs/#swapping). For another practical example, see <a id="ref-listing-5"></a>[Listing 5](#listing-5), where clicking a button in a table with anchor "inner-outer-table" adds an extra row to the end of that table.
5553

5654
# End of Introduction
5755

58-
In this article, a number of important features of HTMX have been covered to make an interactive website possible, entirely driven from HTML and Backend. This overview is certainly not complete, however. The extensive HTMX documentation (Footnote 4) lists many more interesting features, including ways to handle more complex use cases such as validation, caching, and security. If you're enthusiastic about the possibilities, definitely go play around with HTMX with the documentation open beside you. Because you don't bring in any new dependencies on build tools and programming languages, "just trying HTMX" is really easy to do. Especially since the Backend language and framework are also irrelevant, as long as you can serve HTTP Requests and Responses.
56+
In this article, a number of important features of HTMX have been covered to make an interactive website possible, entirely driven from HTML and Backend. This overview is certainly not complete, however. The [extensive HTMX documentation](https://htmx.org/docs/) lists many more interesting features, including ways to handle more complex use cases such as validation, caching, and security. If you're enthusiastic about the possibilities, definitely go play around with HTMX with the documentation open beside you. Because you don't bring in any new dependencies on build tools and programming languages, "just trying HTMX" is really easy to do. Especially since the Backend language and framework are also irrelevant, as long as you can serve HTTP Requests and Responses.
5957

6058
# Away with the Split
6159

@@ -90,13 +88,19 @@ https://online.fliphtml5.com/chjal/ucim/#p=27
9088

9189
# Listings
9290

93-
Listing 1
91+
## <a id="listing-1"></a>Listing 1
9492

9593
```html
96-
<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
94+
<script
95+
src="https://unpkg.com/htmx.org@2.0.4"
96+
integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+"
97+
crossorigin="anonymous">
98+
</script>
9799
```
98100

99-
Listing 2
101+
[↩ Back to text](#ref-listing-1)
102+
103+
## <a id="listing-2"></a>Listing 2
100104

101105
```html
102106
<!DOCTYPE html>
@@ -108,7 +112,9 @@ Listing 2
108112
</head>
109113
```
110114

111-
Listing 3a
115+
[↩ Back to text](#ref-listing-2)
116+
117+
## <a id="listing-3a"></a>Listing 3a
112118

113119
```html
114120
<button hx-post="/clickbait-clicked"
@@ -118,7 +124,9 @@ Click Me! You know you want to! This is not clickbait!
118124
</button>
119125
```
120126

121-
Listing 3b
127+
[↩ Back to text](#ref-listing-3a)
128+
129+
## <a id="listing-3b"></a>Listing 3b
122130

123131
```java
124132
@Component
@@ -134,20 +142,56 @@ public class ClickbaitHandler {
134142
}
135143
```
136144

137-
Listing 4:
145+
[↩ Back to text](#ref-listing-3b)
138146

139-
| Name | Description |
140-
|------|-------------|
141-
| innerHTML | the default, puts the content inside the target element |
142-
| outerHTML | replaces the entire target element with the returned content |
143-
| afterbegin | prepends the content before the first child inside the target |
144-
| beforebegin | prepends the content before the target in the target's parent element |
145-
| beforeend | appends the content after the last child inside the target |
146-
| afterend | appends the content after the target in the target's parent element |
147-
| delete | deletes the target element regardless of the response |
148-
| none | does not append content from response (Out of Band Swaps and Response Headers will still be processed) |
147+
## <a id="listing-4"></a>Listing 4:
149148

150-
Listing 5:
149+
<table>
150+
<thead>
151+
<tr>
152+
<th>Name</th>
153+
<th>Description</th>
154+
</tr>
155+
</thead>
156+
<tbody>
157+
<tr>
158+
<td>innerHTML</td>
159+
<td>the default, puts the content inside the target element</td>
160+
</tr>
161+
<tr>
162+
<td>outerHTML</td>
163+
<td>replaces the entire target element with the returned content</td>
164+
</tr>
165+
<tr>
166+
<td>afterbegin</td>
167+
<td>prepends the content before the first child inside the target</td>
168+
</tr>
169+
<tr>
170+
<td>beforebegin</td>
171+
<td>prepends the content before the target in the target's parent element</td>
172+
</tr>
173+
<tr>
174+
<td>beforeend</td>
175+
<td>appends the content after the last child inside the target</td>
176+
</tr>
177+
<tr>
178+
<td>afterend</td>
179+
<td>appends the content after the target in the target's parent element</td>
180+
</tr>
181+
<tr>
182+
<td>delete</td>
183+
<td>deletes the target element regardless of the response</td>
184+
</tr>
185+
<tr>
186+
<td>none</td>
187+
<td>does not append content from response (Out of Band Swaps and Response Headers will still be processed)</td>
188+
</tr>
189+
</tbody>
190+
</table>
191+
192+
[↩ Back to text](#ref-listing-4)
193+
194+
## <a id="listing-5"></a>Listing 5:
151195

152196
```html
153197
<table id="inner-outer-table">
@@ -170,12 +214,5 @@ Listing 5:
170214
</table>
171215
```
172216

173-
# Footnotes
174-
175-
Footnote 1: https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js
176-
177-
Footnote 2: https://htmx.org/attributes/hx-trigger/
178-
179-
Footnote 3: https://htmx.org/docs/#swapping
217+
[↩ Back to text](#ref-listing-5)
180218

181-
Footnote 4: https://htmx.org/docs/

0 commit comments

Comments
 (0)