JSTL Core Tags: Flow Control Tags 

Joined:
08/13/2009
Posts:
110

April 04, 2010 04:12:14    Last update: July 21, 2010 14:52:58
The tags

<c:if>
The <c:if> tag may be used with or without body content:
<!-- Without body content, used to export variable named by the var attribute -->
<c:if test="testCondition"
var="varName" [scope="{page|request|session|application}"]/>

<!-- With body content, which is inserted into the page when testCondition evaluated to true. -->
<c:if test="testCondition"
[var="varName"] [scope="{page|request|session|application}"]>
body content
</c:if>

In my opinion, the version without body content is pretty much useless (the <c:set> tag is a lot more meaningful for this purpose). If body content exists, it is inserted into the page if the testCondition is true. Optional attributes var and scope may be specified. If var is specified, a variable whose name is the value of var is exported to the associated scope (pageScope if no scope is specified). The type of the exported variable is Boolean and its value is the value of the testCondition.

<c:choose>, <c:when>, <c:otherwise>
These tags imitate the Java control structure if...else if ...else. Typically used like this:
<c:choose>
    <!-- first branch -->
    <c:when test="condition1">
     Branch 1 contents...
    </c:when>

    <!-- second branch -->
    <c:when test="condition2">
    Branch 2 contents...
    </c:when>

    <!-- everything else -->
    <c:otherwise>
    Whatever...
    </c:otherwise>
</c:choose>


<c:forEach>
The <c:forEach> tag iterates over a collection. The syntax is:
<!-- iterate over a collection -->
<c:forEach[var="varName"] items="collection" [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
    body content
</c:forEach>

<!-- loop over a fixed number of times, similar to:
    for (int i = 0; i < 10; i++) {
    ...
    }
  -->
<c:forEach [var="varName"] [varStatus="varStatusName"] begin="begin" end="end" [step="step"]>
    body content
</c:forEach>


The typical use is like this:
<table>
<c:forEach var="product" items="${products}" varStatus="status">
    <tr><td>${status.count}</td><td>${product.name}</td></tr>
</c:forEach>
</table>

where items is the collection to iterate through, var is the current item, varStatus contains the status of the iteration. All implementations of java.util.Collection are supported, as well as arrays of Objects and arrays of primitives. The begin, end, and step attributes can be used to loop over a subset, or skip any number of items.

If items is of type java.util.Map, then the current item is of type java.util.Map.Entry (i.e., the current entry, not the key of the current entry).

The iteration status variable varStatus is of type javax.servlet.jsp.jstl.core.LoopTagStatus. It exposes methods getCount(), getIndex(), isFirst(), isLast(), among others.

<c:forTokens>
The <c:forTokens> tag tokenizes a String and iterates over it. The only difference from <c:forEach> is that the items attribute provides a String to be tokenized instead of a collection. The syntax is:
<c:forTokens items="stringOfTokens" delims="delimiters" 
   [var="varName"] [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
body content
</c:forTokens>


Test it

Make these additions to the expanded test application:
  1. Create a new Java class CoreFlowControl:
    package jstl.demo.handler;
    
    import java.io.IOException;
    import javax.servlet.*;
    import javax.servlet.http.*;
    
    import jstl.demo.DemoHandler;
    
    public class CoreFlowControl implements DemoHandler {
        public void handleRequest(HttpServletRequest req,
    			      HttpServletResponse resp)
    		throws IOException, ServletException {
    	String[] daysOfTheWeek = new String[] {
    				    "Sunday",
    				    "Monday",
    				    "Tuesday",
    				    "Wednesday",
    				    "Thursday",
    				    "Friday",
    				    "Saturday"
    			      };
    	req.setAttribute("store", "open");
    	req.setAttribute("daysOfTheWeek", daysOfTheWeek);
    	req.setAttribute("first3DaysOfTheWeek", "Sunday Monday Tuesday");
    
    	RequestDispatcher d = req.getRequestDispatcher("/coreflowcontrol.jsp");
    	d.forward(req, resp);
        }
    }
    

  2. Create a new JSP (coreflowcontrol.jsp) under webapp:
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <html>
    <head>
    <title>JSTL Core Tags: Flow Control</title>
    
    <style type="text/css">
    body {
        font-family: sans-serif;
    }
    
    table {
        border-collapse: collapse;
    }
    
    td {
        border-style: solid;
        border-width: 1px;
        padding: 4px;
    }
    
    tr.odd {
        background-color: #ddd;
    }
    </style>
    </head>
    
    <body>
    <h2>&lt;c:if&gt; test</h2>
    <c:if test="${store == 'open'}">
    <p>The store is open.</p>
    </c:if>
    
    <h2>&lt;c:choose&gt;, &lt;c:when&gt;, &lt;c:otherwise&gt; test</h2>
    <c:choose>
        <c:when test="${store == 'open'}">
    	<p>The store is open.</p>
        </c:when>
    
        <c:when test="${store == 'closed'}">
    	<p>The store is closed.</p>
        </c:when>
    
    
        <c:when test="${store == 'open' or store == 'closed'}">
            <!-- 
    	This block will never be displayed, even though the test condition
    	may become true. This is because when this is true, one of the 
    	previous blocks must be true - therefore, this block never gets a 
    	chance to display.
    	-->
    	<p>We know the store is open or closed.</p>
        </c:when>
    
        <c:otherwise>
    	<p>We don't know.</p>
        </c:otherwise>
    </c:choose>
    
    
    <h2>&lt;c:forEach&gt; test</h2>
    <table>
    <c:forEach items="${daysOfTheWeek}" var="item" varStatus="status">
        <tr class="${status.index %2 != 0 ? 'odd' : ''}">
    	<td>${status.count}</td><td>${item}</td>
        </tr>
    </c:forEach>
    </table>
    
    <h2>&lt;c:forTokens&gt; test</h2>
    <table>
    <c:forTokens items="${first3DaysOfTheWeek}" delims=" " var="item" varStatus="status">
        <tr class="${status.index %2 != 0 ? 'odd' : ''}">
    	<td>${status.count}</td><td>${item}</td>
        </tr>
    </c:forTokens>
    </table>
    
    </body>
    </html>
    

  3. Compile and package the WAR with: mvn package
  4. Deploy the WAR to a servlet container of your choice (for example, Tomcat 6).
  5. Test the page with this URL (Tomcat 6 running on port 8080):
    http://localhost:8080/jstl-demo/demo/CoreFlowControl

    You may adjust the URL if your servlet container runs on a different port or the web app is bound to a different context root.
Share |
| Comment  | Tags