How can I append the loop index of a c:forEach tag to the attributes of a struts select/text tag?
For example.
<%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="html"%>
<c:forEach begin="2" end="${pageView.guestCount}" varStatus="gC">
<div class="section guest-details">
<html:select property='title_guest<c:out value="${gC.index}"/>'>
<html:options collection="titles" property="code" labelProperty="value" />
</html:select>
</div>
</c:forEach>
throws the following error
javax.servlet.jsp.JspException at org.apache.struts.taglib.html.SelectTag.calculateMatchValues(SelectTag.java:246)
Now, when I debug the code at <html:select ...
it shows that when the property attribute it set, its set as "title_guest<c:out value="${gC.index}"/>"
which could be the cause of the exception above.
Also, I should mention, that if I use the above format for appending the loop index to a standard html tag attribute like a <select>
tag, the code works fine.
For example
<c:forEach begin="2" end="${pageView.guestCount}" varStatus="gC">
<div class="section guest-details">
<select name='title_guest<c:out value="${gC.index }"/>'>
<option value="">Select Title</option>
</select>
</div>
</c:forEach>
Correctly outputs the intended HTML
What am I doing wrong, should I be using EL to create the string that will populate the "property" attribute of the html:select tag?
UPDATE
The following snippet was also tried and that didn't work either
<html:select property="title_guest${gC.index}">
And, neither does this work
<c:set var="guestTitle">title_guest${gC.index}</c:set>
<html:select property="${guestTitle}" styleClass="{required: true}">
<html:options collection="titles" property="code" labelProperty="value" />
</html:select>
JSTL - Core <c:forEach>, <c:forTokens> Tag The <c:forEach> tag is a commonly used tag because it iterates over a collection of objects. The <c:forTokens> tag is used to break a string into tokens and iterate through each of the tokens.
JSTL foreach tag allows you to iterate or loop Array List, HashSet or any other collection without using Java code.
The forEach tag allows you to iterate over a collection of objects. You specify the collection using the items attribute, and the current item is available through a variable named by the var attribute.
The varStatus variables give the user the means to refer to: the first row/node returned by a ForEach Tag; the last row/node returned by a ForEach Tag; the count of the current row/node returned by a ForEach Tag; and the index of the current row/node returned by a ForEach Tag.
After some painful digging around, I seemed to have found the problem and hence the solution. The c:forEach tag does not export the varStatus as a scripting variable and therefore the varStatus variable can not be used in the RT Expr for the property attribute of the html:select tag.
However, the c:forEach does export the varStatus variable as a pageContext attribute, which can be retrieved and used to extract the index/count. The only catch is that you will have to import the javax.servlet.jsp.jstl.core.LoopTagStatus class and use that to manually recreate the varStatus variable so that it can be used inside a scriplet
Here's the snippet of code that worked
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
import="javax.servlet.jsp.jstl.core.LoopTagStatus"
%>
...
<c:forEach begin="2" end="${pageView.guestCount}" varStatus="gC">
<% LoopTagStatus gN = (LoopTagStatus)pageContext.getAttribute("gC"); %>
<html:select property='<%="title_guest"+gN.getIndex()%>'>
<html:options collection="titles" property="code" labelProperty="value" />
</html:select>
</c:forEach>
I don't think this is a clean solution (but could be the only solution). Therefore, I will let the community vote on this answer first (or write a better answer), before I accept it as the final answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With