1. Introduction
This article describes how to iterate over each element in Map object in Thymeleaf.
For more information about how iterators works and how to configure Thymeleaf with Spring Boot please check below links:
Spring Boot with Thymeleaf
Using th:each in Thymeleaf
2. Using th:each
attribute on Maps
Thymeleaf is flexible in many ways. When it comes to interations, you can use not only java.util.List
objects but also any other collection that implements java.util.Iterable
or java.util.Enumeration
or java.util.Iterator
or java.util.Map
interface. We can simply use th:each
in our case, to loop through Map. Note that the iteration variable will be of class java.util.Map.Entry
.
Let's start our example with a simple model that presents the Car
:
package com.frontbackend.thymeleaf.model;
import lombok.Builder;
import lombok.Getter;
import java.util.Date;
@Getter
@Builder
public class Car {
private String vin;
private Color color;
private String model;
private Date productionDate;
}
The color will be a simple enum
of three values: RED, WHITE, BLACK.
package com.frontbackend.thymeleaf.model;
public enum Color {
RED,
WHITE,
BLACK
}
The controller class provides two maps:
- with cars grouped by the color,
- with cars grouped by production year.
@GetMapping("/")
public String getMap(Model model) throws ParseException {
model.addAttribute("carsByColor", carService.randomCars()
.stream()
.collect(Collectors.groupingBy(Car::getColor)));
model.addAttribute("carsByProductionYear", carService.randomCars()
.stream()
.collect(Collectors.groupingBy(
car -> yearFormatter.format(
car.getProductionDate()))));
return "maps";
}
Thymeleaf template that iterates over those two Maps will have the following structure:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Spring Boot Thymeleaf Application - Iteration over Map</title>
</head>
<body>
<h1>Cars by color</h1>
<table>
<tr>
<th>No</th>
<th>Color</th>
<th>Cars</th>
</tr>
<tr th:each="entry, stat : ${carsByColor}">
<td th:text="${stat.index + 1}">1</td>
<td th:text="${entry.key}">color</td>
<td>
<table>
<tr th:each="car : ${entry.value}">
<td th:text="${car.vin}"></td>
<td th:text="${car.model}"></td>
<td th:text="${#dates.format(car.productionDate, 'yyyy-MM-dd')}"></td>
</tr>
</table>
</td>
</tr>
</table>
<h1>Cars by production year</h1>
<table>
<tr>
<th>No</th>
<th>Year</th>
<th>Cars</th>
</tr>
<tr th:each="entry, stat : ${carsByProductionYear}">
<td th:text="${stat.index + 1}">1</td>
<td th:text="${entry.key}">production year</td>
<td>
<table>
<tr th:each="car : ${entry.value}">
<td th:text="${car.vin}"></td>
<td th:text="${car.model}"></td>
<td th:text="${car.color}"></td>
<td th:text="${#dates.format(car.productionDate, 'yyyy-MM-dd')}"></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Note that in our case ${entry.value}
will point to the collection of specific Car
objects grouped by provided attribute.
3. Conclusion
In this tutorial, we showcased the simple example of how to loop through Map in Thymeleaf. We use a map when a key is a color or a year of production and the value is a collection of aggregated cars.
This code can be found in our GitHub repository.
{{ 'Comments (%count%)' | trans {count:count} }}
{{ 'Comments are closed.' | trans }}