PDA

View Full Version : Edit a collection of objects on JSP



pak
Sep 15th, 2004, 09:08 AM
Hi there,

I want to make a JSP for editing a "Construction" object which is populated from data in a database.

The "Construction" object has attributes:
String name
Collection prices

The prices Collection is a Collection of "Price" objects, each of which have attributes:
Double amount
String remark

I can make a JSP where I can edit the "Construction" name (and a single Price object), but how do I handle a Collection of Price objects on the form? How do I "bind" a Collection?

Also, how, on the JSP form, can I create a new Price to add to the existing Collection?

Thanks for any help or pointers,
Peter

Armen
Sep 20th, 2004, 02:47 AM
I have same problem :( . I have 2 variants to sovlve this problem
1 - Server side
2 - Client side

1. Add hidden field in your html form such as:

<INPUT type="hidden" name="<c&#58;out value="$&#123;status.expression&#125;"/>" id="toAddMilestone" > . Now when user click to add or remove entity (in your example - price) just set value for this field to "add" of "remove", using javascript. And then call submit:

<a href="javascript&#58;document.getElementById&#40;'toAddMilestone '&#41;.value='add'; document.forms&#91;0&#93;.submit&#40;&#41;"/>
Then in Form class in Submit method:

protected ModelAndView onSubmit&#40;HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors&#41;
throws Exception &#123;
Job job = &#40;Job&#41; command;
if &#40;!isSubmit&#40;job&#41;&#41; &#123;
if &#40;job.getToAddMilestone&#40;&#41;.matches&#40;"del_-?\\d+"&#41;&#41; &#123;
removeMilestone&#40;job&#41;;
&#125; else &#123;
addMilestone&#40;job&#41;;
&#125;
setFormBackingSessionObject&#40;request, job&#41;;
return showForm&#40;request, errors, getFormView&#40;&#41;&#41;;
&#125;

return super.onSubmit&#40;request, response, job, errors&#41;;

&#125;
- check if user add entity or it is general submit and set prices to your Construction
And you should bind correctly values in onBindAndValidate method to show added prices after page reloading.

2 variant - using javascript. You may create all logic for adding or removing fields and validate values using javascript. And in submit method just parse request parameters.

pak
Sep 28th, 2004, 04:27 AM
Hi, thanks for the reply.

Does your first solution mean that the hidden field maps to an attribute in your "Job" class?

Every time you click the "add" button to generate an extra field you get a submission to your controller. There you create a new "milestone" object which you add to your "job" object (I think), and redirect back to your edit view.

But what about validation? In our case, we have a lot of other fields on the form (mapping to attributes in our class). These are validated by a "validator". If there is a validation error then the "onSubmit" method is never called, and the view is re-generated with error messages - the problem being that the extra fields created by javascript disappear.

Peter

Armen
Sep 28th, 2004, 07:22 AM
I must admit - first variant is a bad idea :-) .
There are many problems appear in code.
I`ve written code, using javascript. I think it is one correct chose.
But problem is, spring can`t help in this way. So you must in method
onBindAndValidate(.....) parse request, get parameters and initialize entity object by self. :cry:


Job job = &#40;Job&#41;command;
handleMilestones&#40;request, job&#41;;//sets several milestones
//each milestone have unique id which generated by javasript&#58;
/*
idSuffix2--;
tblObject.rows&#91;i&#93;.cells&#91;0&#93;.innerHTML = '<input type="text" class="formMax" name="milestoneNameUID'+idSuffix2+'" id="inputName'+idSuffix2+'">';
tblObject.rows&#91;i&#93;.cells&#91;1&#93;.innerHTML = '<input type="text" class="form80" name="milestoneDateUID'+idSuffix2+'">
*/
JobValidator validator = &#40;JobValidator&#41;getValidator&#40;&#41;;
validator.validateMilestones&#40;errors, job&#41;;//and validate by self
super.onBindAndValidate&#40;request, command, errors&#41;;

YSutarko
Sep 30th, 2004, 08:57 PM
The "Construction" object has attributes:
String name
Collection prices

The prices Collection is a Collection of "Price" objects, each of which have attributes:
Double amount
String remark

I can make a JSP where I can edit the "Construction" name (and a single Price object), but how do I handle a Collection of Price objects on the form? How do I "bind" a Collection?


I think you can do it like this in the JSP form (if you named the command name cmd):



<table>
<c&#58;forEach var="sol" items="$&#123;cmd.prices&#125;" varStatus="loopStatus">
<tr>
<td>
<spring&#58;bind path="cmd.prices&#91;$&#123;loopStatus.index&#125;&#93;.amount">
<input type="text" name="$&#123;status.expression&#125;" value="$&#123;status.value&#125;">
</spring&#58;bind>
</td>
<td>
<spring&#58;bind path="cmd.prices&#91;$&#123;loopStatus.index&#125;&#93;.remark">
<input type="text" name="$&#123;status.expression&#125;" value="$&#123;status.value&#125;">
</spring&#58;bind>
</td>
</tr>
</c&#58;forEach>
</table>


this way if you submitted the form, every price contained in the prices collection will be automatically populated

Armen
Oct 1st, 2004, 02:10 AM
Ok, but if I want not only show prices, but add new or delete old?
How could it be done?

pak
Oct 1st, 2004, 07:02 AM
I have done very similar to YSutarko's suggestion for displaying the list, and allowing for editing.

The harder part is implementing adding and deleting items. I have used some of Armen's suggestions for adding extra items, but I am still fighting a little with the deletion part. I haven't implemented it with javascript add/delete rows, but rather with the "hidden" field and a "submit" which specifies that this os for addition of a row. But I might look at a javascript approach which dynamically adds or deletes rows in the HTML - as it might be easier for adding a row, then deleting it again before actually saving the entire object etc.

Thanks,
Peter

cmgharris
Oct 1st, 2004, 08:22 AM
I have done deletions by having an array of boolean in my form backing object, and displaying them as checkboxes with each row. To delete a row, the user ticks the checkbox. Then in the controller, I check through the array and delete any row for which the corresponding boolean is true.

YSutarko
Oct 3rd, 2004, 09:21 AM
to delete, I usually do just like cmgharris said, by adding a Boolean property for the class used in the collection object and use it to bind checkbox values in the form.. about how to use checkboxes with forms, you could see this thread:

http://forum.springframework.org/showthread.php?t=9986

especially this post:



Spring actualy support this. Though he only only documentation I could find is here :

http://www.springframework.org/docs/api/org/springframework/web/bind/ServletRequestDataBinder.html#setFieldMarkerPrefix (java.lang.String)

Basicly what you should do is this:

Code:

<spring:bind path="myForm.booleanFieldName">
<input type="hidden" name="_<c:out value="${status.expression}"/>" value="visible" />
<input type="checkbox" name="<c:out value="${status.expression}"/>" value="true" <c:if test="${status.value}">checked</c:if>>
</spring:bind>


Note the hidden field with same name as the checkbox except for the leading underscore.

Ollie


oh and..



But I might look at a javascript approach which dynamically adds or deletes rows in the HTML - as it might be easier for adding a row, then deleting it again before actually saving the entire object etc.


I dont think using a javascript is a good idea.. because the client can easily disable javascript in their browser..[/code]