到目前为止,我们已经创建了一个主页、一个用户资料页和一个让用户订阅我们的新闻简报的页面......但是我们的产品呢?为此,我们将需要一种方法来迭代集合中的项目,以建立我们的产品页面。
为了在我们的 /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)任何其他对象将被视为包含该对象本身的单值列表