Some time you will see the form containing the button "Add More" . This facility is provided for the user to get the values for unknown number of repeating for some information. for example when you are asking to get the projects details from user, you need to put the option to add the more project for the user since you don't known how many projects user have. In the HTML form, you repeat the particular section to get the multiple values for those elements.
In Html page , you can put the option to add new row of elements or text fields by writing the java script or using JQuery API.
Now, the question is that how to capture the values of dynamically generated text fields on the server. Using the servlet programming you can get the values by using getParameters() method that resultants the array of the parameter having the same name. But this limit you to naming the text fields in the HTML form. To ally this approach, you have to take the same name for the multiple input type fields those will have the similar values. After getting the server side, you need to process these type of fields manually using lots of programing approach. So it is not a feasible solution when there are other approaches available like using Struts2.
Here, I am explaining the approach for the getting over from this problem. We have struts2 MVC framework that has capability to intercept the request parameters submitted from HTML from. It maps the values to the action or bean properties automatically without writing much codes. You need to following some naming convention only. Struts mapping the values of the input type elements of the HTML form to the properties/variable of the action object automatically if you have kept the name of the input type fields and properties same. You can read the struts2 documentation to handle the something in multiple ways.
Now, if there is some multiple fields in the HTML form having repeatedly values, Struts maps those values to the Collection type properties in the Action Object. So to get the values of the field having multiple values but the same name, take the List type variable in Action class. If some properties of the action class pointing other object, struts2 handling it using the naming convention of the input type field.
<INPUT type="text" name="user.addresses.houseNum" />
At the server side, struts2 mappes value of this text filed using OGNL . In the above statement, user is the property of the actiion object and addresses it the property of the user object. Addresses object contains houseNum property in which the value of the above text field will be mapped.
If the User object has the List of Address object , Struts2 to automatically maps the values to this properties using the following naming convention.
<INPUT type="text" name="user.addresses[0].houseNum" />
The value of the text field will be mapped to the property of the first object of the address List contained by the user object.
Here is an application that has the form with id and name text field and option to adding more addresses. User can address any number of address row and all values are processed by server. Here, I am displaying the submitted values in result page but use can change the codding to persist them to database.
index.html
<HTML>
<HEAD>
<TITLE>Add/Remove dynamic rows in HTML table</TITLE>
<SCRIPT language="javascript">
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var counts=rowCount-1;
var cell1 = row.insertCell(0);
var houseNum = document.createElement("input");
houseNum.type = "text";
houseNum.name="user.addresses["+counts+"].houseNum";
cell1.appendChild(houseNum);
var cell2 = row.insertCell(1);
var city = document.createElement("input");
city.type = "text";
city.name="user.addresses["+counts+"].city";
cell2.appendChild(city);
var cell3 = row.insertCell(2);
var country = document.createElement("input");
country.type = "text";
country.name="user.addresses["+counts+"].country";
cell3.appendChild(country);
}
</SCRIPT>
</HEAD>
<BODY>
<form action="submit" method="post">ID : <INPUT type="text" name="user.id" /><br />
Name :<INPUT type="text" name="user.name" /><br />
Addresses :
<TABLE id="addressesTable" width="350px" border="1">
<TR>
<TD>House No.</TD>
<TD>City</TD>
<TD>Country</TD>
</TR>
<TR>
<TD><INPUT type="text" name="user.addresses[0].houseNum" /></TD>
<TD><INPUT type="text" name="user.addresses[0].city" /></TD>
<TD><INPUT type="text" name="user.addresses[0].country" /></TD>
</TR>
</TABLE>
<INPUT type="button" value="Add More" onclick="addRow('addressesTable')" />
<input type="submit" value="SUBMIT"/>
</form>
</BODY>
</HTML>
result.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1>User information</h1>
Name :<s:property value="user.name" /><br/>
Addresses :
<s:iterator value="user.addresses">
<br />
<s:property/>
</s:iterator>
</body>
</html>
web.xml
<web-app>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUB
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<package name="/" extends="struts-default">
<action name="submit" class="UserAction">
<result name="input">index.jsp</result>
<result name="success">result.jsp</result>
</action>
</package>
</struts>
UserAction.java
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
data.User user;
public data.User getUser() {
return user;
}
public void setUser(data.User user) {
this.user = user;
}
public String execute(){
return "success";
}
}
User.java
package data;
import java.util.Collection;
public class User {
int id;
String name;
Collection <Address> addresses;
public Collection<Address> getAddresses() {
return addresses;
}
public void setAddresses(Collection<Address> addresses) {
this.addresses = addresses;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", addresses=" + addresses
+ "]";
}
}
Address.java
package data;
public class Address {
private int houseNum;
private String city;
private String country;
public int getHouseNum() {
return houseNum;
}
public void setHouseNum(int houseNum) {
this.houseNum = houseNum;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [houseNum=" + houseNum + ", city=" + city
+ ", country=" + country + "]";
}
}
Download source
Comments
thanks
Thanks.
Asit Jaiswal
Here you are reading this dynamic values in another html page right.but i want to read it in struts2 action class...
is it possible
Thanks
I'm dynamically creating a row using Javascript function,The row which i have created has a datepicker control along with the textbox,let me know how do i populate value in the textbox with when the user selects the datepicker for the newly added row.
Thanks,
Ramesh.
you can see this link for getting help in hibernate : http://www.programmingforfuture.com/2010/06/hibernate-introduction.html
Thanks for helping,But I have to save dynamic data in different rows in databse with its respected auto incremented ids and i am unable to read dynamic datas seperately or according to number of textfields
I am trying this as such type :
ArrayList arr=new ArrayList();
arr = (ArrayList)(getUser().getAddresses());
System.out.println("String is is-->"+user); //this returns all dynamic values
arr.add(getUser().getAddresses());
System.out.println("arr is-->"+arr); //this returns all dynamic values in arraylist
System.out.println("values are-->"+getUser().getName()); //this returs name
System.out.println("values are-->"+(getUser().getAddresses()).size()); //this returns all dynamic values
for(int i=0;i<(getUser().getAddresses()).size();i++)
{
system.out.println("values are-->"+(String)((ArrayList)(arr.get(i)).get(0))); //it seems runtime error
}
note:I have also changed address.java to ,Plaease help me to Type cast this getUser().getAddresses() or user to String Array Form
package data;
public class Address {
private String city;
public String getCity() {
return city; }
public void setCity(String city) {
this.city = city; }
@Override
public String toString() {
return city; }
}
(because i needed only single dynamic textbox i.e city and also changed in jsp accordingly)
please help me to read dynamic datas seperately according to loop
public String execute(){
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:mydatasource");
//Insert the data of user object,id value can be set to increatment or you can provide unique value yourself as it is a PK.
PreparedStatement ps = con.prepareStatement("insert into userTable(id,name) values(?,?)");
ps.clearParameters();
ps.setInt(1, user.getId());
ps.setString(2, user.getName());
ps.executeUpdate();
ps.close();
//now insert the multiple addresses for this particular user. You have to user user Id as foregain key in address table to identify the addresses for particular user.
PreparedStatement ps2 = con.prepareStatement("insert into userAddress(houseNum,city,country,userId) values(?,?,?,?)");
Collection<Address> addresses = user.getAddresses();
for (Address address : addresses) {
ps2.clearParameters();
ps2.setInt(1, address.getHouseNum());
ps2.setString(2, address.getCity());
ps2.setString(2, address.getCountry());
ps2.setInt(3, user.getId());
ps2.executeUpdate();
}
ps2.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return "success";
}
Thanks Hemraj
Surendra Kumar sharma
I am facing some problem of null pointer exception while trying to read csv file
This code works properly in servlet but not in struts2
kindly help me for reading datas from csv file in struts2
My java code is:-
package question;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ActionContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FileUtils;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.File;
import java.util.*;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Test extends ActionSupport {
//private HttpServletRequest servletRequest;
private HttpServletResponse response;
private HttpServletRequest request;
private static String REAL_PATH = null;
public void setServletRequest( HttpServletRequest request ) {
this.request = request;
REAL_PATH = this.request.getRealPath( "/" );}
public HttpServletRequest getServletRequest() {
return request; }
public void setServletResponse( HttpServletResponse response ) {
this.response = response;}
private static final long serialVersionUID = 1L;
private File csv;
public String addQues()
{
String result = ERROR,sql="",noneOfAbVal="",otherVal="";
if(getCsv() != null)
{
DataInputStream dis = null;
String filename="",msg="",test="",record=null,photoid="",val1="",val2="",str="";
int index=0,j=0,index1=0;
try
{
List items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(getServletRequest());//This line can't recognize
for (FileItem item : items)
{
if (item.getFieldName().equals("csv"))
{
InputStream input=item.getInputStream();
BufferedInputStream bis = new BufferedInputStream(input);
dis = new DataInputStream(bis);
String[] contents=new String[2000];
while( (record=dis.readLine()) != null )
{
contents[j]=record;
//System.out.println("right here--4-->"+contents[j]);
j++;
}
for(int count=0;count<j;count++)
{ index=contents[count].indexOf(",");
val1=contents[count].substring(0,index);
val2=contents[count].substring(index+1);
System.out.println("Val1="+val1);
System.out.println("Val2="+val2);
}
}
}
}
catch(Exception e) { e.printStackTrace();}
}
result=SUCCESS;
return result;
}
public File getCsv() {
return csv; }
public void setCsv(File csv) {
this.csv = csv;
}
}
But if you have a esample using struts1 it would be nice !
Regards from Brasil.
Can we retrieve rowcount value from index.jsp to Action class?
And then set the value of rowCount variable(in javascript) to this field.
document.getElementById('rowCount').value=rowCount;
this field will be submitted alongwith form and you can get this value in action class property "rowCount".
2nd approach:- if you want to get the number of rows, then just get the size of collection addresses in user object.
:)
I am trying to devlope onling billing system in which user can add multiple rows as requirment, but i am stuck here.
It will return array of string having multiple values of a input box name.
thanks for the wonderful post...it was indeed helpful...
I am trying to do the exact thing, but I am wondering how it can be achieved using Struts 1.2.9...
I am stuck badly. If you could help, then it would really be great.
Awaiting your kind response.