Struts2 Iterator Tag - struts2

I am migrating my application from Struts-1 to Struts-2.
The following piece of code uses Struts-1 iterate tag to iterate over a collection "myFormBeanCollection".
Here myFormBean is the form bean,
myFormBeanCollection is one property of myFormBean and is of type ArrayList, this list holds the objects of type "com.xyz.SomeClass".
And next comes a scriptlet element, and then some bean:write...
In scriptlet code: getDate() method is defined in "com.xyz.SomeClass".
<logic:iterate name="myFormBean" property= "myFormBeanCollection" id="someId" type="com.xyz.SomeClass">
<%
String startDate = dateFormat.format(someId.getDate());
%>
<td width="13%" align="center">
<%=startDate%>
</td>
<td width="8%" align="center">
<bean:write name="someId" property="prop_1" />
</td>
</logic:iterate>
How can I migrate this particular code to Struts-2.
I tried using Struts2 iterator tag.
But couldn't succeed in writing the scriptlet.
Not sure on how to call "getDate()" method in the scriptlet as how it was done in above code(Struts-1).
<s:iterator value="myFormBean.myFormBeanCollection">
<%
String startDate = dateFormat.format(""); // Not sure on how to call "getDate()" method as how it was done in above code(Struts-1).
%>
<s:property value="countryName" />,
</s:iterator>
Any help would be greatly appreciated.
Thanks,
Sunil

You wou'dn't, you'd use the <s:date /> tag:
<s:date name="date" format="whatever" />
In fairness, you didn't need to use scriptlet in the original version either--the less work you do in Java in JSP the better: stick to HTML and tags only.
Instead of blindly re-writing the exact same way try to make structural and technical improvements.

Related

Struts2 tags: get a request attribute whose name is itself a value of another request attribute

I have a list of table names in a request attribute, "BillSummaryTables". I am iterating through the list and I want to use each table name to get a request attribute for that particular table name. Corresponding to each table name I have another list in request attribute and I want to iterate through that.
This is what I am doing.
<s:iterator value='#request.BillSummaryTables' var="tableName" status="itStatus">
<div class="contentbox" role="content">
<table class="rpt">
<s:iterator value="#request.get('%{#tableName}').getData()" var="ocRow" status="itStatus">
<tr style="border:1px solid #CCCCCC">
<s:iterator value='#ocRow' var="cell" status="itStatus2">
<td>
<s:property value="#cell.getValue()"/>
</td>
</s:iterator>
</tr>
</s:iterator>
<tr>
<s:iterator value="#request.get('%{#tableName}').getData()" var="ocTotal">
<td>
<s:property value="#ocTotal"/>
</td>
</s:iterator>
</tr>
</table>
</div>
</s:iterator>
I have also tried
#request[<s:property value="#tableName" />].getData()
and
#request['<s:property value="#tableName" />'].getData()
and
#request.%{#tableName}
But nothing is returned in any case.
However, this code works fine if I hard code the values.
i.e. if i use: #request['other_charges'].getData()
Note: I am able to retrieve the list of tableName (#request.BillSummaryTables).
#1) You are using three nested iterators, but both the first and the second have an instance of IteratorStatus called itStatus; they must have different names to work.
#2) If the Lists corresponding to the Table name is, effectively, a List, then you should iterate the list, not the getData() stuff (what is that ?)
#3) Why using request ? why not simply using an HashMap on the Action (with the getter), adding elements dynamically using table names as key ?
#4) This #request[<s:property value="#tableName" />].getData() will obviously not work if put inside another Struts2 tag, like an Iterator (cannot nest Struts2 tags).
However, try something like this (I stripped the second iterator, make it running before, then add stuff), and see if it works (and what it prints):
<s:iterator value='#request.BillSummaryTables' var="tableName" status="statusAllTables">
<div class="contentbox" role="content">
<br/>==== START DEBUG ====
<br/>Current table name: [<s:property value="#tableName"/>]
<br/>Corresponding request object: [<s:property value="#request['%{#tableName}']"/>]
<br/>getData on that object: [<s:property value="#request['%{#tableName}'].getData()"/>]
<br/>===== END DEBUG =====
<table class="rpt">
<s:iterator value="#request['%{#tableName}'].getData()" var="ocRow" status="statusThisTable">
<tr style="border:1px solid #CCCCCC">
<s:iterator value='#ocRow' var="cell" status="statusThisField">
<td>
<s:property value="#cell.getValue()"/>
</td>
</s:iterator>
</tr>
</s:iterator>
</table>
</div>
</s:iterator>
EDIT
Ok, but then why are you using request.setAttribute ? Actions are created per-request... just use a private List<MyObjects> myObjects with its getter (public List<MyObject> getMyObjects()), and call it from JSP with <s:iterator value="myObjects"> (in your case, <s:iterator value="myObjects.data">.
Please note that .getData() in OGNL should become .data (i didn't noticed it before), removing the get, lowering the first letter of the method, and removing round brackets...
Retry and let us know.

Struts2 based quiz application using DB for getting questions and storing results

jsp file
<s:iterator value="questions" status="status">
<table border="3px" bgcolor="yellow">
<tr bgcolor="white" >
<td nowrap><s:property value="QuestionNumber"/></td>
<td nowrap><s:property value="Question"/></td>
</tr>
<tr>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="1"/><s:property value="Option1"/></td>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="2"/><s:property value="Option2"/></td>
</tr>
<tr>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="3"/><s:property value="Option3"/></td>
<td nowrap><input type="radio" name="<s:property value="QuestionNumber"/>" value="4"/><s:property value="Option4"/></td>
</tr>
</table>
<s:hidden> </s:hidden>
</s:iterator>
<s:hidden id="answers" value="answers"/>
<s:submit name="submit" onclick="submitform()"/>
</s:form>
property values are being populated from DB using the Action class.
My problem is that i want to collect the list answers for a quiz and get it to the java classes for evaluation of score. Im not able to get any idea as how to do it
My DB has Questions table with the list of questions with options and correct answer.
I have a Question Bean Object.
You have an Action with a private List<Question> questions;, with Getter and Setter.
You populate your JSP reading the list from the Getter.
You can post that list back from the JSP to the Action's Setter by using OGNL for keeping informations on lines detail.
To do this, use Struts tags (<s:radio instead of <radio ) and set a name including the index of the line.
For example, with a textfield, instead of
<s:iterator value="questions" status="status">
<s:textfield name="question" />
</s:iterator>
use something like (untested, maybe some adjustments needed)
<s:iterator value="questions" status="status">
<s:textfield name="questions[%{#status.index}].question" />
</s:iterator>
Just adapt this for your radio case,
and in the Action you will receive your List fully populated.
(You can even validate a list posted like this usign Visitor validator: not your case, but it's worth knowing).
there are many ways to do this. the easiest way is to implement ParameterAware, checkout the link ParameterAware, then you can get all your parameters like this: (I'm assuming, QuestionNumber is a parameter of your bean question)
String param1 = parameters.get(question.getQuestionNumber);
you can put this line in a loop, so you can get all your parameters...

how to use jsp variable in struts 2 tag

I am wondering if there is any way to use jsp variable in struts 2 tags.
I tried as given below but i did not work.
Suggest me if there is any way to do this.
<%# taglib prefix="s" uri="/struts-tags" %>
<% for(int i=0;i<10;i++)
{
%>
<s:textarea name=%{i} value=%{i}></s:textarea>
<%}%>
please help me.
For any question involving struts2 tags please see: https://struts.apache.org/tag-developers/tag-reference.html
Note the begin and end properties as follows
<s:iterator var="counter" begin="0" end="9" >
<s:textfield name="%{#counter}" value="%{#counter}" /><br/>
</s:iterator>
will produce the desired result.
Edit: just reading your comment to leonbloy you would not use the above, but rather iterate over the collection. Provide a getter which returns your collection. ie:
public List<String> getCollection(){return this.collection};
Then in the jsp you would write:
<s:iterator value="collection">
<s:property/><br/>
</s:iterator>
The above will print out all the strings in the collection.
Did you try this?
<s:property value="%{#i}" />
Read the docs. BTW, that code smells bad, you should try to not mix struts2 tags with JSP Scriptlets (in general -struts2 or anything- you'd try to avoid JSP Scriptlets <% ... %> as much as possible.). Read about the iterator tag.

Struts2: How to set corresponding values of selected row in the VO class from JSP report?

In my Struts2 application I am generating a textual report (in jsp) using iterator tag like
<table>
<tr>
<td>ID</td>
<td>PROOF</td>
<td>DELETE</td>
</tr>
<s:iterator value="listOfVOClassObjects">
<tr>
<td><s:property value="requestId" /></td>
<td><s:property value="requestChecker" /></td>
<td><s:property value="requestProof" /></td>
<td><s:checkbox name="deleteStatus" onclick="submit()"/></td>
</tr>
</s:iterator>
</table>
When user click checkbox page submits and control goes to action class and I need at the same time values of the corresponding row that user has checked should set in setter methods written in VO class so that I can get all these values in my action class.
I tried this by writing a hidden field for every value under iterator tag like
<s:hidden name=" requestId" />
<s:hidden name=" requestChecker" />
<s:hidden name=" requestProof" />
but its not returning the values of corresponding row but the values of all rows separated by commas.
I also tried this by writing these hidden fields outside the iterator tag and that is returning null for every filed.
Please help.
You could update the submit() method to get the correct values and pass them to the action.
In your javascript function, you would set the current values then submit. So you'd have something like this:
<form method="post" action="myAction">
<script>
function submitform(requestId, requestChecker, requestProof) {
document.findElementById('requestId').value = requestId;
document.findElementById('requestChecker').value = requestChecker;
document.findElementById('requestProof').value = requestProof;
document.forms[0].submit();
}
</script>
<s:hidden id="requestId" name="requestId" />
<s:hidden id="requestChecker" name="requestChecker" />
<s:hidden id="requestProof" name="requestProof" />
<table>
<tr>
<td>ID</td>
<td>PROOF</td>
<td>DELETE</td>
</tr>
<s:iterator value="listOfVOClassObjects">
<tr>
<td><s:property value="requestId" /></td>
<td><s:property value="requestChecker" /></td>
<td><s:property value="requestProof" /></td>
<td><s:checkbox name="deleteStatus" onclick="submitForm('<s:property value="requestId" />', '<s:property value="requestChecker" />', '<s:property value="requestProof" />');"/></td>
</tr>
</s:iterator>
</table>
</form>
It depends on what you are doing. If you can recreate the List on the server side then all you need to do is POST the index of the list that you want to get a handle on. For example:
<s:iterator value="myList" status="row">
...
<s:checkbox onclick="deleteRow(%{#row.index})"/>
</s:iterator>
<script>
function deleteRow(index){
location.href=delete?listIndex=index
}
</script>
You would have a setter for listIndex to "receive" the value. This is using a GET, if you want a POST you can do that and make the listIndex a hidden field.
BUT, if you can't recreate the list on the server because the user has modified the list somehow in the browser and you need to preserve that, then you need Struts2 to create the list based on the POST'd parameters. You do that with some special syntax.
<s:iterator value="myList" status="row">
<s:hidden name="myList[%{#row.index}].requestId"/>
<s:hidden name="myList[%{#row.index}].requestChecker"/>
<s:hidden name="myList[%{#row.index}].requestProof"/>
</s:iterator>
This creates fields with names like myList[0].requestId ... myList[5].requestProof. If you have a setter for myList in your action and you POST these parameters to the action, Struts2 will build the List and populate the properties of the objects in the List. You can use Generics List myList to tell Struts2 what kinds of "things" are in your List. You can also look at Type Conversion documentation for Struts2 if Generics doesn't work for you.

how to increment a variable insidet s:iterator tag

I have an s:iterator tag like the following
<s:iterator value="results">
<s:property value="someIntValue"/>
</s:iterator>
At the end of this loop i want the total of someIntValue. In plain java I would do something like this
variable += someIntValue
but can this be done inside the struts2 tag? I looked at documentation for s:set tag but was not able to figure out how to achieve this.
<s:iterator value="users" status="itStatus">
<li>
<s:property value="#itStatus.count" />
</li>
</s:iterator>
Count should give you the value you are looking for. More detail:
link text
From struts in action book:
Sometimes it’s desirable to know status information about the iteration that’s taking
place. This is where the status attribute steps in. The status attribute, when defined,
provides an IteratorStatus object available in the ActionContext that can provide
simple information such as the size, current index, and whether the current
object is in the even or odd index in the
list. The IteratorStatus object can be
accessed through the name given to the
status attribute.
I think this will help you:
<% int variable = 0 %>
<s:iterator value="results">
<s:property value="someIntValue" var="number"/>
<% variable += ${number} %>
</s:iterator>
<%= variable %>

Resources