Mixing index and unindexed list elements in a form? - java

I have a handler like
#RequestMapping(...)
public String get(#RequestParam List<Cmd> rows) {...}
And I use Spring forms tags to generate the inputs. So the JSP code
<c:forEach var="i" begin="0" end="${fn:length(rows)}" >
<form:input path="rows[${i}].name" />
...
</c:forEach>
generates
<input name="rows[0].name" value="...' />
This is all good, but I also want to allow the user to add rows dynamically, so template inputs needs to be written. However, neither name="rows.name" nor name="rows[].name" works, so I have to write code to generate indexes, which is annoying.
Am I missing something here? Is there any better way to do this?
Edit:
BTW, I tried to use Javascript to generate name="rows[n].name" dynamically, but it becomes a problem if the user deletes a row in the middle. A code to rewrite all the indexes seems to be unreasonable.

You can use Javascript to insert new input. Spring generates following
<input name="rows[0].name" value="...' />
Now you want user to enter new value then your Javascript code should generate following line
<input name="rows[1].name" value="...' />
and suppose user wants one more value then,
<input name="rows[2].name" value="...' />
Remember to handle index while generating inputs using Javascript.

try this,
<form:input path="${rows[i].name}" />
instead of
<form:input path="rows[${i}].name" />

Related

Passing multiple values from one page to another

I have the followin question, how will I pass multiple values from one jsp page to another? I have i piece of code here, which works fine, but it only sends one value from one page to another (year):
<form method="post" action="Display data.jsp" name="inputpage" >
<select name="year">
<option value="2010">2010</option>
<option value="2011">2011</option>
</select>
For example if I had another value, for example
String str = "value";
Is it possible to send it using form post method as well? I googled it, and the answer I found included loops and too much code, is there short and simple way of doing it? Many thanks!
When you submit the form all values of the form will be passed, they only need to be inside the form. You can read other values normally by using:
request.getParameter(ParamName)
Take a look at this article for more information
You can send as many variable you want by Form Method.
For sending the value of String Str, assign its value to hidden field as:
<input type="hidden" id="hidden1" value=<c:out value="${variableName}" />
where variableName=str.
Could you use a hidden input inside your form to pass other data using the form post?
<input type='hidden' id='myExtraData' value='hello' />

How to bind a comma separated string to a Java collection (List) in Spring form?

I'm stuck in a situation where I've an input element in a JSP where user enters tags. E.g. java, foo, bar, anotherTag..etc
<c:url var="saveUrl" value="/create" />
<form:form modelAttribute="myAttribute" method="POST"
action="${saveUrl}">
<form:input path="myTitle" />
<form:textarea path="myPost" />
<form:input type="text" id="tagInput"path="???" />
<input type="submit" value="create" />
</form:form>
Now in my domain model corresponding to this input is a
private List<Tag> listOfTags
How to bind a csv to a List. If I enter listOfTags in the path(which is wrong for obvious reasons), I get incorrect binding exception.
How do I convert(or bind) a csv to a List so that the Spring form is submitted properly and the listOfTags get the tags entered in the JSP.
What is the best way to achieve it?
Please help.
I'm not sure but try this. Do a simple html input :
<input type="text" id="tagInput" name="myTags" />
And then in your controller do something like :
#RequestMapping(value="/create", method=RequestMethod.POST)
public void create(..., #ModelAttribute("myAttribute") MyClass myAttribute,
#RequestParam("myTags") String myTags, ...) {
...
myAttribute.setListOfTags(Arrays.asList(myTags.split(",")));
...
}
Note : for more generic ways to bind and convert objects, you may want to take a look at PropertyEditors and Converters.
I suggest try to bind it directly to listOfTags property. And to make it work just add contructor with one argument of String type (or define static method valueOf(String)) to Tag class.
Pretty sure you could do something like this:
<c:forEach var="i" begin="1" end="10">
<form:input type="text" path="listOfTags" />
</c:forEach>
Where you get the user to enter each tag into a separate text input. This is because Spring will automagically bind multiple inputs with the same form name to a List, when it does its binding.
You could use some jQuery sugar to only show one or two and then provide a widget to show more tag inputs. Or even write some cool JS to populate the inputs from a single text input just like StackOverflow does when you add tags.

how to retrieve the name of checkbox if using dynamic name like this<input type="checkbox" name="<%=i%>" /> in servlet?

if provide the dynamic name to the check box and i want to retrieve name of it in servlet for using its value..
In the JSP, use it like the following in a loop
<input type="checkbox" name="<%="checkbox"+(i++)%>" />
Pass another additional varable, which contains the total number of dynamically generated checkboxes.
<input type="hidden" name="num_chk_boxes" value="<%=i%>" />
In the servlet firstly read the total number of checkboxes, from the request, and then do a request.getParameter("checkbox"+i) in a loop with the number as the counter.
Hope that solves your problem

Processing Dynamic forms on the Server Side

I've seen a lot of questions around here about implementing dynamic forms in jQuery or other javascript libraries, and I think I managed to get up and running in setting up a dynamic form for my test purposes.
My question is whats the best practice in naming my form fields and processing them on the server side.
I am trying to implement a contact like form where the user can add multiple phone numbers (and types) as well as multiple addresses (and types) something similar to the code below, this is the code block that will be duplicated dynamically.
<div id="phones">
<label>Phone Number</label><input type="text" name="phone1" value="" />
<label>Type</label><input type="text" name="type1" value="" />
</div>
Then I will have a +/- link or button to add another phone or remove a phone. When I submit the form, whats the best way to handle the combo of name/type
Should I have the names like indicated above with a postfix of an id like phone1 / type1 or should I use the array naming like phone[] / type[] and match the pairs on the server according to the index.
I am using java (not sure if it makes a difference if it is java or php or whatever) but what would be a best practice of doing this.
Thanks
Square brackets with indexes seem to be what most frameworks expect, but it does completely depend on your framework. In the Java world, given that there are about a million different frameworks, you have to start from what your framework expects, and adapt your Javascript code appropriately.
The only Java framework I'm familiar enough with to know the answer is Stripes, and it would want square brackets. If your bean had a property
private List<Address> addresses;
public List<Address> getAddresses() { return addresses; }
public void setAddresses(final List<Addresses>) { this.addresses = addresses; }
then the inputs would need names like "addresses[0].street1", "addresses[0].street2", etc. When you add a new block for a new address, you'd have the same fields with "1" instead of "0".
A different Java framework, however, might do things in completely different ways.
In your case, you should number the field specifically. Don't use array naming convention, which caused me big headache in the past.
If you use arrays, you will run risk of mismatching type and phone values when parameters are missing. Some browsers simply ignore empty values.
To help server retrieve all the parameters, I normally put the number of fields in a hidden field. For the form will look like this,
<div id="phones">
<input type-"hidden" name="count" value="3" />
<ul>
<li>
<label>Phone Number</label><input type="text" name="phone1" value="" />
<label>Type</label><input type="text" name="type1" value="" />
</li>
<li>
<label>Phone Number</label><input type="text" name="phone2" value="" />
<label>Type</label><input type="text" name="type2" value="" />
</li>
<li>
<label>Phone Number</label><input type="text" name="phone3" value="" />
<label>Type</label><input type="text" name="type3" value="" />
</li>
</ul>
</div>

How to POST multiple "record sets" from an HTML Form to JSP or a Java Servlet?

Does JSP or any related lightweight technology like JSTL perform HTTP POST "data grouping", or support form element "indexing" in the way PHP does?
For example, you can create an HTML form with the following inputs:
<input type="text" name="person[1][name]" />
<input type="text" name="person[1][age]" />
<input type="text" name="person[2][name]" />
<input type="text" name="person[2][age]" />
... and PHP will parse that into a nested associative array automatically. Do JSP, Java Servlets, or any related spec or tool provide this kind of translation out of the box?
The goal is to submit multiple "record groups" in a single form, and process them server-side in JSP or a Servlet.
Requirements:
The functionality cannot rely on JavaScript
No full frameworks like Spring, Struts, or the like
I'm trying to avoid reinventing the wheel with my own naming convention and manual String parsing / Regex
Related Links:
How this is accomplished in PHP
Another PHP example from ONLamp
Try this,
<input type="text" name="personNames" />
<input type="text" name="personAges" />
<input type="text" name="personNames" />
<input type="text" name="personAges" />
You should consider to create input fields using a loop, you don't need to postfix the name even. and get parameter values like this in your servlet,
String[] names = request.getParameterValues("personNames");
String[] ages = request.getParameterValues("personAges");
It will come in the same order as defined in your HTML. Then loop over it like below,
for( String name : names) {
System.out.println(name);
}

Categories