Using htmx with Spring Boot and Thymeleaf
Tags: springboot, frontend, webdev
Published: 2023-08-15 12:09:18

Htmx allows **building complex web applications that feel like an SPA** without relying on Angular or React. The client's behavior is mainly controlled by attributes within the HTML code that execute an Ajax request and integrate the result into the DOM - **perfectly fitting for server-side rendering with Thymeleaf**.

## Basic setup

To keep the example simple, let's setup a Spring Boot application based on Thymeleaf and Bootstrap. We use WebJars to provide the libraries for the client.

```gradle
dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.springframework.boot:spring-boot-starter-thymeleaf')
    implementation('org.webjars:bootstrap:5.3.1')
    implementation('org.webjars.npm:htmx.org:1.9.4')
    developmentOnly('org.springframework.boot:spring-boot-devtools')
}
```
_&nbsp; Required dependencies for using Thymeleaf, Bootstrap and htmx_

Our controller will render our index page and already contains a second endpoint for loading additional info via AJAX later on. 

```java
@Controller
public class HomeController {

    @GetMapping("/")
    public String index() {
        return "index";
    }
    
    @PostMapping("/furtherInfo")
    public String furtherInfo() {
        return "furtherInfo";
    }

}
```
_&nbsp; Controller to output our templates_

Let's prepare a simple template for our index page. We won't use a dedicated layout here. 

```html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Homepage</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link th:href="@{/webjars/bootstrap/5.3.1/css/bootstrap.min.css}" rel="stylesheet" />
        <script th:src="@{/webjars/bootstrap/5.3.1/js/bootstrap.bundle.min.js}" defer></script>
        <script th:src="@{/webjars/htmx.org/1.9.4/dist/htmx.min.js}" defer></script>
    </head>
    <body>
        <main class="my-5">
            <div class="container">
                <h1 class="mb-4">Homepage</h1>
                <p class="mb-5 js-greeting">Hello World!</p>
                <button>Change greeting</button>
            </div>
        </main>
    </body>
</html>
```
_&nbsp; Our Thymeleaf template in resources/templates/index.html_

How we **create ourselves a complete project** is described further below. If everything is set up correctly, after starting the application we can reach our home page at `http://loclahost:8080/`.

## Activate htmx behavior

Without further configuration htmx is not enabling any functionality. Let's quickly add some logic to our button, which will **call the second endpoint of our controller and replace our greeting message**.

```html
<button th:hx-post="@{/furtherInfo}"
        hx-trigger="click"
        hx-target=".js-greeting"
        hx-swap="outerHTML">Change greeting</button>
```
_&nbsp; Extend our button with htmx logic_

We use Thymeleaf's ability here to populate any HTML attribute - in this case we create the link to our endpoint, which will be contained in the `hx-post` attribute. On click, **htmx will now call the endpoint via Ajax and replace our targeted `<p>` element** with the response. A more detailed explanation of the attributes can be found in [the htmx documentation](https://htmx.org/docs/).

```html
<p class="mb-5 js-greeting">Hello Pluto!</p>
```
_&nbsp; Updated greeting in furtherInfo.html_

Alternatively, we could add the `hx-boost="true"` attribute to our body element. This will cause all links and forms to be picked up by htmx, so **all actions are performed without reloading the browser** - creating an SPA-like user experience. Two possible approaches to error handling of htmx requests in Spring Boot are described [in this article](https://bootify.io/frontend/htmx-error-handling-in-spring-boot.html).

## Generate propotype with htmx setup

With Bootify **the described setup can be generated directly in the browser**. The frontend with htmx is available in the Free plan without registration.

![](https://s3-eu-central-1.amazonaws.com/bootify-prod/ext/img/frontend/builderHtmxSetup.png "Options to generate a Spring Boot app with htmx")
_&nbsp; Options to generate a Spring Boot app with htmx_

The current versions of all libraries are always used, and an individual database schema including CRUD functions can be added if required.

[**&raquo; Start Project on Bootify.io**](https://bootify.io/)