Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append loop index of c:forEach tag to Struts HTML tag attributes?

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>
like image 672
Salman Paracha Avatar asked May 11 '11 20:05

Salman Paracha


People also ask

What is the syntax for forEach loop in JSTL?

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.

Which JSTL tags are used for looping an ArrayList?

JSTL foreach tag allows you to iterate or loop Array List, HashSet or any other collection without using Java code.

Which tag is used to iterate over the elements in a collection or an array?

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.

What is varStatus Jstl?

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.


1 Answers

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.

like image 61
Salman Paracha Avatar answered Nov 24 '22 18:11

Salman Paracha