I am able to display an ArrayList of beans in a JSP form using JSTL by looping through the list and outputting the bean properties in a HTML input tag.
<c:forEach items="${listOfBeans}" var="bean">
<tr>
<td><input type="text" id="foo" value="${bean.foo}"/></td>
<td><input type="text" id="bar" value="${bean.bar}"/></td>
</tr>
</c:forEach>
How do I code the JSP so that when the page submits then the updated values are in the appropriate item of the the ArrayList?
Given this simplified model:
public class Item {
private Long id;
private String foo;
private String bar;
// ...
}
Here's how you can do it provided ${items} is List<Item>:
<c:forEach items="${items}" var="item">
<tr>
<td>
<input type="hidden" name="id" value="${item.id}" />
<input name="foo_${item.id}" value="${fn:escapeXml(item.foo)}" />
</td>
<td>
<input name="bar_${item.id}" value="${fn:escapeXml(item.bar)}" />
</td>
</tr>
</c:forEach>
(note the importance of fn:escapeXml() as XSS attack prevention)
So, basically, you need to set the item's unique identifier as a hidden input field in each row as shown in above snippet:
<input type="hidden" name="id" value="${item.id}" />
And you should in turn use this id as suffix of name of all input fields in the same row such as:
<input name="foo_${item.id}" ... />
In the servlet, you can collect all values of <input type="hidden" name="id" ...> from all rows by request.getParameterValues(). Just loop over it and then grab the individual inputs by id.
for (String id : request.getParameterValues("id")) {
String foo = request.getParameter("foo_" + id);
String bar = request.getParameter("bar_" + id);
// ...
}
You can also do this all without that id and grab all inputs by name as an array like so name="foo" and request.getParameterValues("foo"), but the ordering of request parameters is not under your control. HTML forms will send it in order, but the enduser can easily manipulate the order.
No need for JavaScript mess here.
See also:
Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern
ServletRequest.getParameterMap() returns Map<String, String[]> and ServletRequest.getParameter() returns String?
Send an Array with an HTTP Get
Related
<form:form action="approveAccount.html" method="GET">
<input type="submit" value="approvAll"/>
<p>Following Accounts are Pending to approve</p>
<c:forEach items="${accountIdList}" var="val">
<li>${val}</li>
</c:forEach>
</form:form>
val is the value that is fetched from database, I want to add a submit button and want to use this fetched value to do some stuffs, how many value get fetched is dynamically decided, how todo that.. here in this scenario, I am getting account id which admin needs to approv, so by adding textbox, admin can assign the role to the this account and then submit the to the database and this all happen with that clk of button
Suppose, in your service class, you have list of accountIds like this
ArrayList<Integer> accountIdList = new ArrayList<>();
accountIdList.add(1);
accountIdList.add(2);
accountIdList.add(3);
& you have added this list into HTTP Session object for further use like
session.setAttribute("accountIds",accountIdList);
In your JSP, you can then use JSTL for-each loop to create dynamic buttons & textboxes as below
<c:forEach var="ids" items="${session.accountIds}" varStatus="loop">
<input type="text" name="role${loop.index}" />
<input type="submit" value="<c:out value=${ids} />" />
</c:forEach>
I hope this helps.
If I understood your question right, your trying to get multiple ids and it's associated roles when the user click submit button. You can try the following to get them:
JSP:
<form:form action="approveAccount.html" method="GET">
<input type="submit" value="approvAll"/>
<p>Following Accounts are Pending to approve</p>
<c:forEach items="${accountIdList}" var="val">
<input type="text" value="${val}" name="id">
<select name="role">
<option value="admin">Admin</option>
<option value="user">user</option>
</select>
</c:forEach>
</form:form>
Servlet:
String [] txt = request.getParameterValues("id");
String [] role = request.getParameterValues("role");
for (int i = 0; i < txt.length; i++){
System.out.println(txt[i]+" "+role[i]);
}
I am passing a list inside a session from servlet to a jsp as follows :
HttpSession session = req.getSession();
session.setAttribute("list1", arrayList);
Inside the JSP I am printing the list as follows :
<form action="Save" method="post">
<c:forEach items="${list1}" var="item">
${item}<br>
<c:set var="stringArray" value="${fn:split(item, ',')}" />
<input type="text" name="Deivice" value="${stringArray[0]}" />
<input type="text" name="DTA" value="${stringArray[1]}" />
<input type="text" name="Type" value="${stringArray[2]}" />
<br>
</c:forEach>
<input type="submit" value="Save">
</form>
Now I want to retrieve the list in a servlet (after the user modifies it in the UI)
How can I pass the values back to the servlet ? Basically, I want to pass a list,alow the user to modify the contents of the list on the UI and want the modified contents of the list in a servlet.
Simply submit the form and get the values in Servelt using request.getParameterMap() or request.getParameterValues(String) that returns String[] for each parameter name that is submitted.
For e.g
String[] devices = request.getParameterValues("Deivice");
I am a beginner to Java EE and I have started to implement a small online book Store shopping cart example to learn and apply basic concepts.
When user search for a book, it gives a list of suggested books then user starts to add to cart those by clicking the Add To Cart Button.
I have used hidden input type to send it.
Below is my JSP code.
<%
List<BookDetails> newlist = new ArrayList<BookDetails>();
newlist = (List)session.getAttribute("currentSession");
%>
<table>
<form name="DisplayResult" action="addToCartServlet">
<tr>
<td><b>Book</b></td><td><b>Price</b></td>
</tr>
<%
for (int i = 0; i < newlist.size(); i++)
{
BookDetails book1 =newlist.get(i);
%>
<tr>
<td><%=book1.getBookName()%></td>
<td><%=book1.getPrice()%></td>
<td>
<input type="hidden" name="ISBN" value="<%=newlist.get(i).getISBN()%>">
<input type="submit" name="action" value="Add to Cart">
</td>
</tr>
<% }%>
</form>
</table>
I'm accessing it through servlet as below.
String isbn= request.getParameter("ISBN") ;
But it every times takes only the first search result value for any button click.
How can I get each unique ISBN for each book?
You need form per row to pass different data for each row
See
why business logic should be moved out of JSP?
he #Jigar Joshi telling right, at same method look like.
the text box as follows:
<form:input path="contacts[${status.index}].book" />
<tr>
<td align="center">${status.count}</td>
<td><input name="contacts[${status.index}].book" value="${contact.book}"/></td>
<td><input name="contacts[${status.index}].price" value="${contact.price}"/></td>
</tr>
explanation of line is:
contacts[${status.index}].book
Its will generate each rows as follows:
contacts[0].book // mapped to first item in contacts list
contacts[1].book// mapped to second item in contacts list
contacts[2].book// mapped to third item in contacts list
explanation of line is coding format:
<form:input path="contacts[${status.index}].book" />
Then instead of converting it to following HTML code:
<input name="contacts[0].book" />
<input name="contacts[1].book" />
<input name="contacts[2].book" />
It converts it into following:
<input name="contacts0.book" />
<input name="contacts1.book" />
<input name="contacts2.book" />
I have a struts2 form that is programatically generated upon request. The element names for all the fields are the same namely idA and paramValue because I am passing the form values as array and looping through it for database inserts. Inserts are now OK, but I am still finding out how to validate the form.
Here's the form:
<s:iterator value="sysParamList" var="sysParam">
<tr>
<td>
<strong><s:property value="paramName" /></strong>
<input type="hidden" name="idA" value="<s:property value="id" />" />
</td>
<td>
<input type="text" name="paramValue" />
</td>
</tr>
</s:iterator>
The properties in my action are declared like
private String[] idA;
private String[] paramValue;
And I pass these in my DAO as-is. The DAO does the looping through the array for database insert.
I can validate forms using jquery.validate IF the form is hard coded in the JSP.
I currently have the following code and the data is displayed fine.
<logic:iterate name="myList" id="product" indexId="iteration" type="com.mycompany.MyBean">
<tr>
<td> <bean:write name="product" property="weight"/> </td>
<td> <bean:write name="product" property="sku"/> </td>
<td> <bean:write name="product" property="quantity"/> </td>
</tr>
</logic:iterate>
But now I need to make the "quantity" part modifiable. The user should be able to update that field, press submit and when its sent to the server, "myList" should automatically update with the new quantities.
I've tried searching for help on this but all I keep finding is examples on how to display data only, not modify it. Any help would be appreciated.
So this is tricky, because there are many things to get done in order for it to work. First, declare your tags inside the iterator with the html tags, with attribute INDEXED=TRUE and an ID DIFFERENT THAN THE NAME, i also took out the "indexId" attribute to use the simple "index" word for the index:
<logic:iterate name="myList" id="myListI" type="com.mycompany.MyBean">
<tr>
<td> <html:input name="myListI" property="weight" indexed="true"/> </td>
<td> <html:input name="myListI" property="sku" indexed="true"/> </td>
<td> <html:input name="myListI" property="quantity" indexed="true"/> </td>
</tr>
after that, in order for struts to be able to get and set the attributes of your beans, you need to declare EXTRA get and set methods inside your collection object, using the name you wrote in the id of the iterate tag. In this case, you would write 2 extra get and set methods for the "myListI" :
public void setMyListI(int index, myBean value){
this.myList.add(value);
}
public myBean getMyListI(int index){
return this.myList.get(index);
}
I think Th0rndikes answer is mostly correct. My implementation is slightly different, so it might be worth trying this as well.
Form
private List<Parameter> activeParameters;
public List<Parameter> getActiveParameters() {
return activeParameters;
}
public Parameter getParam(int index){
return this.activeParameters.get(index);
}
JSP
<logic:iterate name="MyForm" property="activeParameters" id="param">
<tr>
<td><bean:write name="param" property="prompt"/></td>
<td><html:text name="param" property="value" indexed="true"/></td>
</tr>
</logic:iterate>
In summary, I didn't use Type in the iterate tag, using the property tag instead. In the bean adding a getter with matched the name of the iterate ID in the JSP (param) with an index as a method parameter did the trick.
Take a look at this: http://wiki.apache.org/struts/StrutsCatalogLazyList
Indexed Properties
Struts html tags have an indexed attribute which will generate the
appropriate html to populate a collection of beans when the form is
submitted. The trick is to name the id attribute to the same as the
indexed property.
For example the following jsp...
<logic:iterate name="skillsForm" property="skills" id="skills">
<html:text name="skills" property="skillId" indexed="true"/>
</logic:iterate>
...will generate the following html
<input type="text" name="skills[0].skillId value="..."/>
<input type="text" name="skills[1].skillId value="..."/>
....
<input type="text" name="skills[n].skillId value="..."/>
When the form is submitted BeanUtils will first call the
getSkills(index) method to retrieve the indexed bean followed by
setSkillId(..) on the retrieved bean.
Theoretically, the indexed attribute of the struts html tags could be used for this:
Valid only inside of logic:iterate tag. If true then name of the html tag will be rendered as "id[34].propertyName". Number in brackets will be generated for every iteration and taken from ancestor logic:iterate tag.
But, there is no corresponding indexed attribute on the html:errors tag, which limits its usefulness. Also, the required combination of id, name and property attributes can be rather confusing.
I found it easier to use jsp scriptlets to generate the property name including the iteration index. The following code requires that your form has a string array property "quantity".
<% int idx=0; %>
<logic:iterate ...>
<html:text property='<%= "quantity[" + idx + "]" %>'/>
<html:errors property='<%= "quantity[" + idx + "]" %>'/>
<% i++; %>
</logic:iterate>