如何使用JSP的c:forEach和c:if过滤最后的条目?

4
我正在开发一个使用JSP页面的Spring MVC应用程序,遇到了问题。这个问题更多的是创意问题而不是代码问题,但是请听我阐述:
该应用程序基本上接收一个食谱(字段名称、问题描述、问题解决方案等),并在创建时给它添加一个ID。
我想要在首页展示最近创建的 3个 食谱。我已经编写了一段代码,可以显示似乎是最早 3个 创建的食谱:
<c:forEach var="recipe" items='${recipes}'>
    <c:if test="${recipe.id < 4}
        <div class="span4">
            <h3<c:out value="${recipe.inputDescProb}"></c:out></h3>
            <p><c:out value="${recipe.inputDescSol}"></c:out></p>
            <p><a class="btn" href="/recipes/${recipe.id}">Details &raquo</a></p>
        </div>
    </c:if>
</c:forEach>

有没有关于如何显示最近创建的3个食谱的想法?

你这样做是因为你正在使用ajax或类似的东西重新获取食谱列表吗? - Luiggi Mendoza
不,没有使用ajax。目前只是通过本地地图进行本地操作,没有持久化。 - jsfrocha
3个回答

7
不需要检查长度,只需使用varStatus变量的.last属性。
<c:forEach var="recipe" items="${recipes}" varStatus="status">
  <c:if test="${not status.last}">
    Last Item
  </c:if>
<c:forEach>

顺便提一下,你也可以获得.first.count


6

使用fn:length() EL函数来计算食谱的总数。在使用任何EL函数之前,我们需要导入必要的tag库

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

然后我们使用<c:set>将总数设置为页面范围属性。
<c:set var="totalRecipes" value="${fn:length(recipes)}" />

<c:forEach> 允许您使用 varStatus 属性获取循环计数器。计数器的作用域局限于循环中,并且它会自动为您递增。这个 循环计数器 从1开始计数。

<c:forEach var="recipe" items='${recipes}' varStatus="recipeCounter">
  <c:if test="${recipeCounter.count > (totalRecipes - 3)}">
    <div class="span4">
      <h3<c:out value="${recipe.inputDescProb}"></c:out></h3>
      <p><c:out value="${recipe.inputDescSol}"></c:out></p>
      <p><a class="btn" href="/recipes/${recipe.id}">Details &raquo;</a></p>
    </div>
  </c:if>
</c:forEach>

编辑:使用LoopTagStatus类的count属性来访问迭代计数器的当前值,在您的EL中为${varStatusVar.count}


很好的解释,我只是浅显地介绍了这些JSTL方法,但我理解了它们的工作原理。不过我还是遇到了一个错误。当我加载页面时没有任何条目,一切都正常。但是当我输入一个或多个食谱并返回主页时,会出现以下错误:Cannot convert javax.servlet.jsp.jstl.core.LoopTagSupport$1Status@ffed1d of type class javax.servlet.jsp.jstl.core.LoopTagSupport$1Status to class java.lang.Long 我猜问题出在 For 循环上面? - jsfrocha
使用 count 属性并在 ${recipeCounter.count > (totalRecipes - 3)} 中加括号,以避免运算符优先级的副作用。 - Ravi K Thapliyal

1
你可以使用${fn:length(recipes)}将当前计数与整个集合大小进行比较:
<c:set var="total" value="${fn:length(recipes)}"/>


<c:forEach var="recipe" items='${recipes}' varStatus="status">
  <c:if test="${status.count > total - 3}">
    <div class="span4">
      <h3<c:out value="${recipe.inputDescProb}"></c:out></h3>
      <p><c:out value="${recipe.inputDescSol}"></c:out></p>
      <p><a class="btn" href="/recipes/${recipe.id}">Details &raquo</a></p>
    </div>
  </c:if>
</c:forEach>

编辑:

您首先需要导入fn,以使JSTL的fn可供使用:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

我尝试了一下,但是出现了/WEB-INF/jsp/home.jsp(31,30) PWC6287: The attribute prefix fn does not correspond to any imported tag library。第30行:<div class="row">(没问题),第31行:<c:set var="total" value="${fn:length(recipes)}" varStatus="count"/>,我需要导入什么才能让它工作? - jsfrocha
varStatus 属性使用不正确。它应该在 c:forEach> 内部使用。有关详细信息,请参阅我的答案。 - Ravi K Thapliyal
好的,我已经导入了JSTL函数,但是仍然出现“PWC6131:根据TLD,标签设置无效的varStatus属性”,这是指<c:set var="total" value="${fn:length(recipes)}" varStatus="count"/>(我认为上面的评论总结了一切——如果可以的话,正确的用法是什么?) - jsfrocha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接