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.
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')
}
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.
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index";
}
@PostMapping("/furtherInfo")
public String furtherInfo() {
return "furtherInfo";
}
}
Controller to output our templates
Let's prepare a simple template for our index page. We won't use a dedicated layout here.
<!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>
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.
<button th:hx-post="@{/furtherInfo}"
hx-trigger="click"
hx-target=".js-greeting"
hx-swap="outerHTML">Change greeting</button>
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.
<p class="mb-5 js-greeting">Hello Pluto!</p>
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.
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.
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.
Top comments (0)