I am trying to build a time tracking page where I display the project name, tasks and the hours billed for each day.
Here is the object I have on the Java side:
ProjectTO project1 = new ProjectTO();
project1.setProjectName("Project ABC");
TreeMap tasks = new TreeMap();
tasks.put("100_t1", "Requirement");
tasks.put("100_t2", "Development");
project1.setTasks(tasks);
TreeMap hours = new TreeMap();
hours.put("100_t1:Mon", "8");
hours.put("100_t1:Wed", "7");
project1.setHours(hours);
I'll need to look through this object to display values on the screen. Here is what I have on the JSP Page:
<s:iterator value="activeProjects">
<tbody>
<tr>
<td><p><s:property value="projectName"/></p></td>
</tr>
<s:iterator value="tasks">
<tr>
<td><s:property value="value"/></td>
<td><s:property value="hours[%{key+':Mon'}]"/></td>
<td><s:property value="hours[%{key+':Tue'}]"/></td>
..........
</tr>
</s:iterator>
</tbody>
</s:iterator>
The problem is figuring out how to display the hours. The code snippet shown above does not work. I can get it to work by using <s:set var="mon" value="%{key+':Mon'}">
and referencing it in my td tags - hours[#mon]).
Is there a better solution?
Edit:
Thanks Dave. You are right. I am looking for hours["100_t1:Mon"]
.
When I am iterating over the object in the view layer, the '100_t1' will need to be dynamically inserted based on the key of the task row i am iterating over. 'Mon', 'Tue' can be hardcoded.
I am going to see if I can do this better outside of the View layer as you recommended. As of now this is what I have working for me.
<s:iterator value="activeProjects">
<tbody>
<tr>
<td><p><s:property value="projectName"/></p></td>
</tr>
<s:iterator value="tasks">
<s:set var="mon" value="%{key+':Mon'}"/>
<s:set var="tue" value="%{key+':Tue'}"/>
<s:set var="wed" value="%{key+':Wed'}"/>
<s:set var="thu" value="%{key+':Thu'}"/>
<s:set var="fri" value="%{key+':Fri'}"/>
<s:set var="sat" value="%{key+':Sat'}"/>
<s:set var="sun" value="%{key+':Sun'}"/>
<tr>
<td><s:property value="value"/></td>
<td><s:property value="hours[#mon]"/></td>
<td><s:property value="hours[#tue]"/></td>
<td><s:property value="hours[#wed]"/></td>
<td><s:property value="hours[#thu]"/></td>
<td><s:property value="hours[#fri]"/></td>
<td><s:property value="hours[#sat]"/></td>
<td><s:property value="hours[#sun]"/></td>
</tr>
</s:iterator>
</s:iterator>
Final Edit:
The following statement helps me avoid having to use s:set tags. I should have surrounded hours[key + ':Mon']
within %{}
.
value="%{hours[key + ':Mon']}"/>
also this works too
value="hours[key + ':Wed']"
You're short-circuiting the OGNL evaluation you actually want.
The full OGNL expression you're looking for is actually hours["100_t1:Mon"]
:
<s:property value="%{hours[key + ':Mon']}"/>
(IMO) you should be attach the hours to a task more concretely; as it is you're kind of subverting OOP paradigms by using maps and ad-hoc relationships.
Also, you know precisely how many days there are in a week, present the JSP with a list of daily hours. This avoids doing work in the view layer where testing is more difficult.
If you choose to not follow OOP/MVC norms, you can eliminate some redundancy like this:
<s:iterator value="{'Mon', 'Tue', ...etc...}" var="d">
<s:set var="hrs" value="%{hours[key + ':' + #d]}"/>
<td><s:property value="%{#hrs ? #hrs : 'N/A'}"/></td>
</s:iterator>
Again, I feel pretty strongly this is the wrong place to do this type of work.