Complete Guide on using Thymeleaf with Spring Boot

Thymeleaf is a Java-based server-side template engine. It process HTML5, XML, and XHTML etc. Thymeleaf can work in both web and non-web environments. Thymeleaf can be easily integrated with Spring and Spring Boot applications. It is mainly used for view layers in web MVC applications.

Spring boot makes it extremely easy to integrate and use Thymeleaf in spring boot applications. In this article, we will learn how we can use Thymeleaf to build our view layer of the spring boot application. It will be explained with the help of examples.

How to integrate Thymeleaf with Spring Boot?

Spring boot already comes with Thymeleaf support. Similar to other most-used dependencies, auto-configuration for this template engine is also provided in Spring boot. We just need to add the starter dependency for Thymeleaf.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.6.2</version>
</dependency>

No additional configuration is needed. It is auto-managed by the starter dependency.

However, In order to use Thymeleaf tags in our HTML pages, we need to add support for Thymeleaf using below:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
...
</html>

How to access Model Attributes in Thymeleaf?

The first thing we require in a web MVC application is to pass some data from the controller to view. That data is then parsed to show on the user screen. In the spring boot application, we add various model attributes that are passed to the view. We are going to learn how these model attributes are read and parsed in the Thymeleaf template.

String Model Attribute in Thymeleaf

We use th:text=”${attributename}” when we access simple model attributes like String. Suppose, we have added the below model attribute in our controller class:

model.addAttribute("name","John");

Below is our HTML code/Thymeleaf to display the above model attribute in view:

<p th:text="${name}"></p>

Integer / Boolean Model Attribute in Thymeleaf

Similarly, int and boolean model attributes can also be accessed with ${attributeName}. Here is a small example:

model.addAttribute("id",1);
model.addAttribute("active",true);

Below HTML is used to print 1 and true in view:

<p th:text=${id}/>
<p th:text=${active}/>

Model Attribute List in Thymeleaf

One of the most asked questions about Thymeleaf is how to send a list of objects into Thymeleaf and how to iterate a list in Thymeleaf and print list values.

Let’s suppose, we have an Employee object and it has states id, name, etc. Now, our controller is sending a list of employees to Thymeleaf.

public class Employee {
	private Long id;
	private String name;
    // Constructor, Setters, Getters ...
}

Let’s see our controller code to add a list of employees in the model attribute:

List<Employee> employees = new ArrayList<>();
// Here Employee objects are getting added in the employees list
model.addAttribute("employees", employees);

Finally, we will look at how to iterate over the list in Thymeleaf spring boot. We use th:each in Thymeleaf to iterate over the list or any other collection. This will loop the enclosing tags for n number of times, where n is the size of the list. It extracts and presents each object from the list in an object and we can simply print it. Let’s look at the code to understand better:

	<table style="border:solid 1px black;">
		<thead>
			<tr>
				<th>ID</th>
				<th>NAME</th>
			</tr>
		</thead>
		<tbody>
			<tr th:each="employee: ${employees}">
				<td th:text="${employee.id}" />
				<td th:text="${employee.name}" />
			</tr>
		</tbody>
	</table>

In the above example, employees is the list object which we have added in model attributes. employee represents the object present in the employees list at the current position.

Model Attribute Map in Thymeleaf

Similarly, we can iterate any other collection like Map in Thymeleaf. Iterating over Map differs from iterating over List in Thymeleaf because the former have key,value structure.

Let’s directly jump into code to understand how to iterate over Map in Thymeleaf. Below is our controller code:

Map<Long, String> employeeMap = new HashMap<>();
//employees is the list of Employee objects
for (Employee emp : employees) {
    employeeMap.put(emp.getId(), emp.getName());
}
model.addAttribute("employeesMap", employeeMap);

Let’s look at the Thymeleaf template to iterate and print Map:

<table style="border:solid 1px black;">
    <thead>
	    <tr>
		    <th>ID</th>
			<th>NAME</th>
		</tr>
	</thead>
	<tbody>
		<tr th:each="emp: ${employeesMap}">
			<td th:text="${emp.key}" />
			<td th:text="${emp.value}" />
		</tr>
	</tbody>
</table>

Now, we are using key and value keywords to get the key and value for the map respectively.

If-Else Conditions in Thymeleaf

We can impose if-else conditions in Thymeleaf. If-else conditions are implemented in Thymeleaf using if and unless keywords. We use tags th:if and th:unless for imposing if and else conditions respectively.

Let’s introduce boolean values in our controller and pass them to our view via model attribute.

model.addAttribute("active", true);

Let’s see Thymeleaf template:

<p>User is 
    <span th:if="${active}" th:text="Active"></span>
    <span th:unless="${active}" th:text="Inactive"></span>
</p>

The result will be “User is Active” if active is true otherwise “User is Inactive”.

Switch Case in Thymeleaf

We can use th:switch and th:case to implement switch cases in Thymeleaf. Let’s look at the example. We have introduced one more String variable department in our previous Employee class.

public class Employee {
...
private String department;

//getters and setters
...
}

We will modify our controller class to add department model attribute and pass it to the view / Thymeleaf template:

List<String> departments = new ArrayList<>();

departments.add("IT");
departments.add("INFRA");
departments.add("CS");
departments.add("HR");
departments.add("ADMIN");
		
for (int i = 0; i < 5; i++) {
    Employee emp = new Employee();
	emp.setId((long)i+1);
	emp.setName("Emp "+emp.getId());
	emp.setDepartment(departments.get(i));	
    service.addEmployee(emp);		
}

List<Employee> employees = service.getAll();
model.addAttribute("employees", employees);

Let’s implement th:switch and th:case :

<table style="border: solid 1px black;">
		<thead>
			<tr>
				<th>ID</th>
				<th>NAME</th>
				<th>DEPARTMENT</th>
			</tr>
		</thead>
		<tbody>
			<tr th:each="employee: ${employees}">
				<td th:text="${employee.id}" />
				<td th:text="${employee.name}" />
				<td th:switch="${employee.department}">
				 <span th:case="'INFRA'" th:text="Infrastructure"></span>
				 <span th:case="'CS'" th:text="Customer Support"></span>
				 <span th:case="'HR'" th:text="Human Resources"></span>
				 <span th:case="'ADMIN'" th:text="Administration"></span>
				 <span th:case="'IT'" th:text="Information Technology"></span>
				</td>

			</tr>
		</tbody>

Fetch and Display Values from a Properties File(application.properties)

We will now retrieve values from the application.properties value and display it using Thymeleaf. We can use @environment.getProperty() directly into the Thymeleaf template to extract the values from a properties file.

// suppose, we have a "app.name" property in properties file
<p th:text="${@environment.getProperty('app.name')}"/>

Forms in Thymeleaf

We have different attributes in Thymeleaf to handle user input in a form. Attribute th:action is used for providing the action URL of the form, th:object defines the name of the object associated with the form, and th:field attributes inside the form represent the state(fields) associated with the object.

Let’s understand it with help of an example. Here, we are enhancing our existing example of Employees. Instead of creating employees in the backend, we will now create the Employee using Thymeleaf forms:

<form action="#" th:action="@{/add}" th:object="${employee}"
		method="post">
		<table>
			<tr>
				<td><label th:text="Name" /></td>
				<td><input type="text" th:field="*{name}" /></td>
			</tr>
			<tr>
				<td><label th:text="Department" /></td>
				<td><select th:field="*{department}">
						<option th:value="'INFRA'" th:text="Infrastructure"></option>
						<option th:value="'CS'" th:text="Customer_Support"></option>
						<option th:value="'HR'" th:text="Human_Resources"></option>
						<option th:value="'ADMIN'" th:text="Administration"></option>
						<option th:value="'IT'" th:text="Information_Technology"></option>
				</select></td>
			</tr>
			<tr>
				<td><input type="submit" value="Submit" /></td>
			</tr>
		</table>
	</form>

Let’s understand the example:

  • th:action="@{/add}" make a call to the controller with /add mapping after submission of form.
  • method="post" ensures the call will be made to PostMapping.
  • th:object="${employee}" defines that this form data represents object employee.
  • This employee object has been passed to Thymeleaf through Model Attribute from the controller which redirected to this form. Like this: model.addAttribute("employee", new Employee());
  • th:field="*{name}" binds the provided field to the object. For example, here name represents employee.name and value provided in this input field will be bound to employee.name.

The above form after submission will call the below controller method:

	@PostMapping("/add")
	public String addEmployee(@ModelAttribute Employee employee) {	
		service.addEmployee(employee);
		return "redirect:/employees";
	}

We have returned “redirect:/employees” that’ll call the controller method with /employees mapping. In this method, we are retrieving the list of employees and passing it to view.

Conclusion

In this tutorial, we have learned Thymeleaf with examples. Starting with the integration of Thymeleaf in Spring Boot till using it in the application of spring boot, we tried to cover everything about Thymeleaf with Spring Boot.

Newsletter Updates

Enter your name and email address below to subscribe to our newsletter

Leave a Reply