Sending Data in HTMX Requests (3 Ways)

Fikayo Adepoju
5 min readApr 6, 2024

--

Introduction

TL;DR: We can all agree that HTMX is great right?

After several years of heaping up huge node_modules folders with hundreds of packages just to build a simple homepage in frameworks like Reactjs, Vuejs and Angular, we now have an alternative approach that brings back the simplicity of the old days where we just add one Javascript link at the top of our page and start building amazing interactivity in our Frontend applications.

Instead of Javascript-heavy frontends and virtualizing the DOM, HTMX takes a different approach by making “HTML Great Again” through the addition of enhanced hypermedia controls to native HTML elements.

One of the biggest examples is the ability to use any tag (<div>, <span>, <input />, etc) to trigger an HTTP request based on an event, using the standard HTTP methods: POST , GET , PUT, and DELETE

In this article, I’ll be showing you how you can send data along with your HTTP requests in HTMX and we will be looking at 3 ways you can do that.

By the way, if you’re still trying to get your hands solid on HTMX, you can checkout my course: The Complete HTMX Course: Zero To Pro with HTMX [Discount included]

Enough talk, let’s get started.

#1: Using a <form /> Tag

The first, and probably easiest strategy, is to wrap the element making the request inside an HTML <form> tag. Inside this <form> tag, we can then add <input /> elements for each piece of data that we want to send.

Once the request is sent, all the data contained in the <input /> fields within the form will be sent along with the request

Example: Let’s say we want to process a login request by sending an email/password combo and the button below triggers the request with an hx-post

<button hx-post="http://localhost:1330/login">
Submit
</button>

The first step is to place this button inside an HTML form like below:

<form>

<button hx-post="<http://localhost:1330/login>">
Submit
</button>
</form>

We will then add <input> tags for the email and password we want to send along by specifying the name of the parameters with the name attribute of the <input> elements.

<form>

<input type="email" name="userEmail" />

<input type="password" name="userPassword" />

<button hx-post="http://localhost:1330/login">
Submit
</button>

</form>

This way, HTMX will automatically recognize the data in the input fields as the data you want to send with the POST request and they will be sent accordingly.

Do note that this request is sent as Form Data, thus you need to make sure that your server accepts form data. For example, on an Express.js server, make sure that you have this middleware setup:

app.use(bodyParser.urlencoded({extended: true}))

#2: Using hx-vals (Sending JSON Data)

Our previous data sending strategy sends data to the server as Form data, this might not be appropriate in a number of cases. So, let’s look at how we can send data in JSON format using a JSON object.

Instead of wrapping our data items in a form tag this time we use a special HTMX tag, hx-vals , on the requesting element to load our JSON object as the payload of the request.

Example: Sending Login Details with a JSON object

So let’s say we want to send this JSON data along with our request:

{
"userEmail": "htmxceo@x.com"
"userPassword": "htmxrocks"
}

We will simply pass this object to the hx-vals attribute on our requesting element. However, it is important to note that because this JSON object uses double quotes for its keys and values, the hx-vals attribute should wrap the object in single quotes like below:

<button hx-post="http://localhost:1330/login"
hx-vals='{
"userEmail": "htmxceo@x.com"
"userPassword": "htmxrocks"
}'>
Submit
</button>

Now when you click this button, the JSON payload will be sent along with the request.

Just like I noted in the previous section, ensure that your server can receive requests in JSON format in order to access this payload on the server-side.

On an Express.js server, you should have this middleware setup:

app.use(bodyParser.json());

Passing Variables in your Request

You might be asking, what if I want to send variables within my JSON object? As we all know, you can’t always hardcode values into your JSON payload, some of the values will come from user-submitted data or state variables.

So let’s assume we have these two variables that hold our email and password

const email = "htmxceo@x.com";
const password = "htmxrocks"

We can simply pass this into our JSON object by prefixing the value of hx-vals with js: and then replace our values inside the JSON object with variables. Below is our previous example refactored to use variables instead of hardcoded strings.

<script>
const email = "htmxceo@x.com";
const password = "htmxrocks";
</script>

...

<button hx-post="http://localhost:1330/login"
hx-vals='js:{
"userEmail": email
"userPassword": password
}'>
Submit
</button>

This format also allows you to use Javascript functions or expressions as values of your JSON object keys.

#3: Using hx-include

This strategy is used for input fields that are not in anyway positionally close to or related to the requesting element (not collocated) but the requesting element needs to include their data in the HTTP request.

To better understand this, in our first strategy, the input fields were wrapped as siblings with requesting element, the HTML button, inside a form tag.

But what if the input field is at a totally different position away from the button in the DOM but you need to include the information in that input field in your request? that’s where hx-include comes in.

Example: We need to send the user id of a user in order to process their payment request. Let’s say we have the HTML structure below:

<div>
<input type="text" name="userID" />

<div>
<h3>Product Name</h3>
<img src="/imags/product-001" />
<p>
Product Description
</p>
</div>

</div>


<div>
<button hx-post="http://localhost:1330/processpayment">
Pay Now
</button>
<div>

As you can see from the markup above, the button making the request and the input field for the userID data item are miles apart and are not even located in the same container element. However, we still want to be able to pick the data in this input field and send it in our request. So how do we achieve that?

The first thing we will need to do is to give the <input /> element that we want to target an id in order to access it:

<input type="text" name="userID" id="myUserID" />

We can then include it in our request by placing a hx-include attribute on the requesting element and use a CSS selector with the ID of the input field as the value like below:

<button hx-post="http://localhost:1330/processpayment"
hx-include="#myUserID">
Pay Now
</button>

This way, when the button is clicked to trigger the request, the data in the input field will be passed along in the request body.

How awesome is that 😃.

So, those are the 3 strategies for passing data in HTTP requests when using HTMX.

If you have found this article useful and you need a full comprehensive guide on what HTMX is and how to use it to build frontend applications, you can get my HTMX course here for 90% off.

If you want to learn how to build fullstack apps with HTMX, you can also grab my HTMX + Go: Build Fullstack Applications with Golang and HTMX course also at an amazing discount.

You can also subscribe to my newsletter for more amazing HTMX and software engineering content.

Happy Coding ☺️

--

--