📜 1. Passing a List to Thymeleaf and Looping Through It
Suppose we want to display a list of users.
🔵 Controller (Java):
File: HelloController.java
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class HelloController {
@GetMapping("/users")
public String showUsers(Model model) {
List<String> users = List.of("Stanley", "Marina", "Karina", "Alex");
model.addAttribute("users", users);
return "users"; // users.html
}
}
✅ We pass a List<String>
called users
into the model.
🔵 Thymeleaf Template:
File: users.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>User List</title>
</head>
<body>
<h1>Users:</h1>
<ul>
<li th:each="user : ${users}" th:text="${user}">User</li>
</ul>
</body>
</html>
✅ th:each
loops over the list. ✅ ${user}
outputs each username.
🔵 Result in Browser (localhost:8080/users):
Users:
- Stanley
- Marina
- Karina
- Alex
📜 2. Conditionally Rendering Based on Role (th:if / th:unless)
Suppose we want to show admin-only buttons if the user is an admin.
🔵 Controller (Java):
Add to your HelloController.java
:
@GetMapping("/dashboard")
public String showDashboard(Model model) {
model.addAttribute("username", "Stanley");
model.addAttribute("role", "ADMIN"); // or "USER"
return "dashboard"; // dashboard.html
}
🔵 Thymeleaf Template:
File: dashboard.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Dashboard</title>
</head>
<body>
<h1>Welcome, <span th:text="${username}">User</span>!</h1>
<div th:if="${role == 'ADMIN'}">
<button>Manage Users</button>
<button>View Admin Reports</button>
</div>
<div th:unless="${role == 'ADMIN'}">
<p>You are a regular user.</p>
</div>
</body>
</html>
✅ th:if
shows admin buttons only if role is "ADMIN"
. ✅ th:unless
shows different content if the user is not an admin.
🔵 Result:
- If
role == ADMIN
➔ sees Manage Users buttons. - If
role == USER
➔ sees “You are a regular user.” message.
📜 3. Using Fragments (Header/Footer/Layout Reuse)
Suppose you want one common header and footer for every page.
🔵 Create a Fragment File:
File: /templates/fragments/header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div th:fragment="siteHeader">
<header style="background-color: lightblue; padding: 10px;">
<h1>My Website</h1>
<nav>
<a href="/hello">Home</a> |
<a href="/users">Users</a> |
<a href="/dashboard">Dashboard</a>
</nav>
</header>
</div>
</body>
</html>
✅ th:fragment="siteHeader"
defines a reusable fragment.
🔵 Now Include the Header in Other Pages
Example for dashboard.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Dashboard</title>
</head>
<body>
<div th:replace="fragments/header :: siteHeader"></div>
<h2>Dashboard Content Goes Here</h2>
</body>
</html>
✅ th:replace="fragments/header :: siteHeader"
means:
- “Find the file
/fragments/header.html
“ - “Use the part named
siteHeader
“ - “Insert it here at runtime.”
🔵 Result:
Every page that uses this will automatically get a common consistent header.
🎯 Final Quick Summary
Feature | Example |
---|---|
Looping | <li th:each="item : ${items}"> |
Conditional rendering | <div th:if="${role == 'ADMIN'}"> |
Fragments reuse | <div th:replace="fragments/header :: siteHeader"> |
✅ Clean. ✅ Reusable. ✅ Professional structure.
📢 Important Extras:
- You can nest fragments (layouts).
- You can pass parameters into fragments.
- You can compose layouts like master pages.