Exploring HTMX
[HTMX](https://htmx.org/), or Hypertext Markup Extensions, is a JavaScript library that allows developers to build web applications using HTML instead of JavaScript. It was created by Carson Gross and was initially released on November 24, 2020. You can integrate HTMX into an HTML document by adding a script tag that links to the HTMX library. HTMX extends HTML with custom attributes that allow developers to: * Access AJAX, CSS Transitions, WebSockets, and Server-Sent Events directly in HTML * Dynamically update web pages * Insert server responses into specific parts of a web page without redrawing the entire page HTMX uses HTML attributes to: * Swap out parts of the user interface with a response from a server * Define the HTTP method to be used when making a request to the server * Specify the element on the page where the response from the server will be displayed * Determine what user action will trigger the HTMX request HTMX allows developers to: * Avoid sending too much JavaScript to the browser * Simplify the process of building web applications * Write code that resembles ordinary HTML code and is easy to understand ## Working Example This is a basic example of a Task List application created in HTMX and Javascript. The application allows users to add tasks, mark tasks as complete, and delete tasks. Before we start, there's a caveat: **The application as currently written doesn't preserve the tasks when the page is reloaded**. To save the tasks between page loads, you would need to store them in a database or use local storage, Indexed DB or similar technologies. Specific HTMX attributes used in this example: * `hx-post`: Sends an HTTP POST request to the server at the specified URL * `hx-on`: Defines the event that will trigger the HTMX request. In this case when the `AddTask` is submitted ```html
const taskElement = document.createElement("div");
taskElement.className = "task"; // Assign a class for styling purposes
taskElement.id = `task-${taskId}`; // Unique ID for each task using the task ID
// Set the inner HTML of the task element, including task text and buttons
taskElement.innerHTML = `
${taskText}
`;
// Add the new task element to the task list
taskList.appendChild(taskElement);
// Clear the input field after adding the task
taskInput.value = "";
}
// Toggle the completion state of a task
function toggleComplete(taskId) {
// Find the task element using its unique ID
const taskElement = document.getElementById(`task-${taskId}`);
// Toggle the "completed" class to change the appearance of the task
taskElement.classList.toggle("completed");
}
// Delete a task
function deleteTask(taskId) {
// Find the task element using its unique ID
const taskElement = document.getElementById(`task-${taskId}`);
// Remove the task element from the DOM
taskElement.remove();
}
```
This example works with an in-memory task list, and the tasks are added, marked as complete, and deleted using HTMX attributes. In a more serious application, you would need to handle these actions on the server side and update the client-side view accordingly.
## Fetching External Data
This example uses an endpoint from [REST Countries](https://restcountries.com/) to fetch country data and display it on the page.
The `load-btn` button triggers an HTMX request to fetch data from the REST Countries API. The response is an array of country objects, which are then displayed on the page using a template. The instantiation will be done in Javascript.
```html
```
The Javascript adds an HTMX-specific event listener (`htmx:afterOnLoad`) to the document body. This event is triggered after an HTMX request has been completed. The event listener parses the response data, clears the previous results, and populates the `countries-list` element with the country data using the template.
The code checks if the response is empty and returns if there is no data to display. It then iterates over the country data, replacing placeholders in the template with the actual country data. The resulting HTML is appended to the `countries-list` element.
```js
document.body.addEventListener("htmx:afterOnLoad", (event) => {
const responseData = event.detail.xhr.response;
if (!responseData) return;
const countries = JSON.parse(responseData);
const countriesContainer = document.getElementById('countries-list');
const template = document.getElementById('country-card-template').innerHTML;
countriesContainer.innerHTML = "";
countries.forEach(country => {
const cardHtml = template
.replace('{{name}}', country.name?.common || "N/A")
.replace('{{region}}', country.region || "N/A")
.replace('{{population}}', country.population.toLocaleString())
.replace('{{capital}}', country.capital ? country.capital[0] : "N/A")
.replace('{{flag}}', country.flags?.png || "");
countriesContainer.innerHTML += cardHtml;
});
});
```
One final detail that may be interesting is that we can use `from` in the `hx-trigger` attribute to target a different element than the one that triggered the event. For example, if we want to trigger an HTMX request when a user types in an input field, we can use the `from` attribute to specify the input field.
## Links and Resources
* [HTMX — high power tools for HTML](https://htmx.org/)
* [What is HTMX? Why it Matters? and How to use it.](https://dev.to/alexmercedcoder/what-is-htmx-why-it-matters-and-how-to-use-it-10h3)
Click the button to fetch and display data about countries.
No countries loaded yet. Click the button above to fetch data.
{{name}}
Region: {{region}}
Population: {{population}}
Capital: {{capital}}