到目前为止,我们已经创建了一个主页、一个用户资料页和一个让用户订阅我们的新闻简报的页面......但是我们的产品呢?为此,我们将需要一种方法来迭代集合中的项目,以建立我们的产品页面。
为了在我们的 /WEB-INF/templates/product/list.html 页面中显示产品,我们将使用一个表格。我们的每个产品都将显示在一行中(<tr>元素),因此对于我们的模板,我们需要创建一个模板行 —— 它将示范我们希望每个产品如何被显示,然后指示 Thymeleaf 重复它,每个产品仅展示一次。
标准方言正好为我们提供了一个属性:th:each。
对于我们的产品列表页面,我们将需要一个控制器方法,从服务层检索产品列表并将其添加到模板上下文中。Java 部分代码如下:
@Override
public void process(final IWebExchange webExchange, final ITemplateEngine templateEngine,
final Writer writer) throws Exception {
final ProductService productService = new ProductService();
final List<Product> allProducts = productService.findAll();
final WebContext ctx = new WebContext(webExchange, webExchange.getLocale());
ctx.setVariable("prods", allProducts);
templateEngine.process("product/list", ctx, writer);
}然后我们将在我们的模板中使用th:each来迭代产品列表。如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" media="all" href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}"/>
</head>
<body>
<h1>Product list</h1>
<table>
<thead>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
<th>COMMENTS</th>
</tr>
</thead>
<tbody th:remove="all-but-first">
<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
<td>
<span th:text="${#lists.size(prod.comments)}">2</span> comment/s
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:unless="${#lists.isEmpty(prod.comments)}">view</a>
</td>
</tr>
<tr class="odd">
<td>Blue Lettuce</td>
<td>9.55</td>
<td>no</td>
<td>
<span>0</span> comment/s
</td>
</tr>
<tr>
<td>Mild Cinnamon</td>
<td>1.99</td>
<td>yes</td>
<td>
<span>3</span> comment/s
<a href="comments.html">view</a>
</td>
</tr>
</tbody>
</table>
<p>
<a href="../home.html" th:href="@{/}">Return to home</a>
</p>
</body>
</html>你在上面看到的那个 th:each="prod : ${prods}" 属性值意味着“对 ${prods} 结果中的每个元素,重复执行这个模板片段,在 prod 变量中临时存放当前元素内容”。让我们给我们看到的每一个东西起个名字:
(1)我们将称 ${prods} 为迭代表达式或迭代变量。
(2)我们将称 prod 为迭代变量或简称 iter 变量。
注意,prod 迭代变量的作用范围是 <tr> 元素,这意味着它可以用于 <td> 等内部标签。
java.util.List 类并不是唯一一个可以在 Thymeleaf 中用于迭代的值。下面是可以通过 th:each 属性迭代的值:
(1)任何实现 java.util.Iterable 的对象
(2)任何实现 java.util.Enumeration 的对象
(3)任何实现 java.util.Iterator 的对象,其值将在迭代器返回时被使用,不需要在内存中缓存所有的值
(4)任何实现 java.util.Map 的对象。当迭代 Map 时,iter 变量将是 java.util.Map.Entry 类
(5)任何数组
(6)任何其他对象将被视为包含该对象本身的单值列表