Struts 2 Adding / Removing Dynamic rows and getting values in struts 2 action.

This tutorial covers that how to create a dynamic list of text fields based on a collection to enter user input and then assign that input back to the object. Also let us see, how to map these dynamics values with object and handle in struts 2 action.

In many situations, you may not be knowing , how many rows are required for input in advance. For eg. i) adding passengers list when you book tickets ii) Entering experience / qualification details when you apply for a Job iii) ordering list of items when you shop online, etc… In this situation, you need to add or remove rows dynamically. So let us see , how to add / remove Dynamic rows and getting values in struts 2 action.

Adding and Removing rows can be done

1. Using JavaScript

2. Using Java Code (Sending Request to action)

In our example, rows & elements are added dynamically using JavaScript and are deleted using Java code i.e by sending the request to action. In struts 2, when we send these dynamically created values to action, each row will be mapped to the corresponding object. This object represent each row in a table and are stored in a list. So basically list of objects are mapped. Struts 2 does this mapping automatically. Just we need to create necessary java beans and declare variable in the action class. The action class needs to be mapped in the struts.xml. Now let us try with an example.

In our example, let us create a sample application for booking ticket in a bus. In this you need to get,

1. Journey Details : Bus Number, Bus Name, From Station, To Station , Fare , List of Passengers – Ticket.java

2. Passenger details : S.No, Name, Gender, Age – PassengerDetails.java

Let us design a JavaBean class for Journey Details (Ticket.java)


package net.javaonline.dto;

import java.io.Serializable;

import java.util.Date;
import java.util.List;

public class Ticket implements Serializable{

 private long ticketNo; // to be auto generated.
 private String busNo;
 private String busName;
 private String journeyDate;
 private String fromStation;
 private String toStation;
 private double fare;
 private double totalFare;
 private Date bookedOn;
 private List<PassengerDetails> passengerDetail; // to capture list of passenger details

 public List<PassengerDetails> getPassengerDetail() {
 return passengerDetail;
 }

public void setPassengerDetail(List<PassengerDetails> passengerDetail) {
 this.passengerDetail = passengerDetail;
 }

public String getBusNo() {
 return busNo;
 }

public void setBusNo(String busNo) {
 this.busNo = busNo;
 }

public String getBusName() {
 return busName;
 }

public void setBusName(String busName) {
 this.busName = busName;
 }

 public String getJourneyDate() {
 return journeyDate;
 }

public void setJourneyDate(String journeyDate) {
 this.journeyDate = journeyDate;
 }

public String getFromStation() {
 return fromStation;
 }

public void setFromStation(String fromStation) {
 this.fromStation = fromStation;
 }

public String getToStation() {
 return toStation;
 }

public void setToStation(String toStation) {
 this.toStation = toStation;
 }

public double getFare() {
 return fare;
 }

public void setFare(double fare) {
 this.fare = fare;
 }

public double getTotalFare() {
 return totalFare;
 }

public void setTotalFare(double totalFare) {
 this.totalFare = totalFare;
 }

public Date getBookedOn() {
 return bookedOn;
 }

public void setBookedOn(Date bookedOn) {
 this.bookedOn = bookedOn;
 }

}

Now Let us design JavaBean class for  Passenger  Details ( PassengerDetails.java)


package net.javaonline.dto;

import java.io.Serializable;

public class PassengerDetails implements Serializable{

 private short sno;
 private String name;
 private String age;
 private String gender;

 public short getSno() {
 return sno;
 }
 public void setSno(short sno) {
 this.sno = sno;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getAge() {
 return age;
 }
 public void setAge(String age) {
 this.age = age;
 }
 public String getGender() {
 return gender;
 }
 public void setGender(String gender) {
 this.gender = gender;
 }

}

In out example, Passenger list is not fixed. Ticket may be booked with one passenger or even with 10 passengers… So we need to create dynamic rows ans elements to accept Passenger details.

Dynamically adding passenger details :

1. Using Java code

        For this you need to add a blank object (with sno=1) in the list for creating a first blank row with S.No in view. After entering values, for adding more rows you need to press AddMore button. Now the request goes to action and adds a blank row (with sno=sno+1) and rendered.

2. Using JavaScript code:

       In this example, i have used javascript code for adding dynamic rows and elements. The JSP (TicketBook.jsp) code is given below.

TicketBook.jsp


<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>ticket Details - Struts2 Dynamic Table Example</title>

<script type ="text/javascript">

function addMorePassengerRow(tableID) {
 var table = document.getElementById(tableID);
 var rowCount = table.rows.length;
 var row = table.insertRow(rowCount); //to insert blank row

 var cell1 = row.insertCell(0);   //to insert first column
 var snoCol = document.createElement("input");
 snoCol.type = "text";
 snoCol.name="ticket.passengerDetail["+(rowCount-1)+"].sno";
 snoCol.value=rowCount;
 cell1.appendChild(snoCol);

 var cell2 = row.insertCell(1); //to insert second column
 var nameCol = document.createElement("input");
 nameCol.type = "text";
 nameCol.name="ticket.passengerDetail["+(rowCount-1)+"].name";
 cell2.appendChild(nameCol);

var cell3 = row.insertCell(2); // to insert 3rd column
 var genderCol = document.createElement("input");
 genderCol.type = "text";
 genderCol.name="ticket.passengerDetail["+(rowCount-1)+"].gender";
 cell3.appendChild(genderCol);

 var cell4 = row.insertCell(3);  //to insert 4th column
 var ageCol = document.createElement("input");
 ageCol.type = "text";
 ageCol.name="ticket.passengerDetail["+(rowCount-1)+"].age";
 cell4.appendChild(ageCol);

 var cell5 = row.insertCell(4);   // to insert 5th column
 var rowRemoveCol = document.createElement("a");
 var text = document.createTextNode("Delete");
 rowRemoveCol.appendChild(text);
 rowRemoveCol.setAttribute("href","javascript:goSubmit("+(rowCount-1)+")");
 rowRemoveCol.name="reqlink[]";
 cell5.appendChild(rowRemoveCol);

 return false;

}

function goSubmit(rowindex)
{
 document.ticketForm.rowindex.value=rowindex;
 document.ticketForm.action="delete";
 document.ticketForm.submit();

 }

</script>

</head>
<body>

<h3>Ticket Booking</h3>
<s:actionerror/>

<s:form name="ticketForm" action="ticketBook" method="post" theme="%{currentTheme}">
<s:hidden name="rowindex"/>

<TABLE id="ticketTable" width="350px" border="1">
 <TR>
 <td>
 Bus Number : <s:textfield name="ticket.busNo" label="Bus Number"/>
 </td>
 <td>
 Bus Name : <s:textfield name="ticket.busName" label="Bus Name"/>
</td>
</TR>
 <TR>
 <td>
 From Number : <s:textfield name="ticket.fromStation" label="From Station"/>
</td>
<td>
 To Station : <s:textfield name="ticket.toStation" label="To Station"/>
</td>
</TR>

<TR>
 <td>
Fare : <s:textfield name="ticket.fare" label="Fare (to be displayed Automatically)"/>
 </td>
 <td>
Journey Date : <s:textfield name="ticket.journeyDate" label="Journey Date"/>
</td>
</TR>

</TABLE>

Add / Remove Passenger Details :
<TABLE id="pdTable" border="1">
 <TR>
 <TD>S.No.</TD>
 <TD>Name</TD>
 <TD>Gender</TD>
 <TD>Age</TD>
 <TD>Action</TD>
 </TR>

<s:iterator value="ticket.passengerDetail" status="cnt" var="passgrList">
<tr>
<TD> <s:textfield name="ticket.passengerDetail[%{#cnt.count-1}].sno" /> </TD>
<TD> <s:textfield name="ticket.passengerDetail[%{#cnt.count-1}].name" /> </TD>
<TD> <s:textfield name="ticket.passengerDetail[%{#cnt.count-1}].gender" /> </TD>
<TD> <s:textfield name="ticket.passengerDetail[%{#cnt.count-1}].age" /> </TD>
<td><a href="javascript:goSubmit(<s:property value='#cnt.count-1'/>)">delete</a></td>
</tr>
</s:iterator>

</TABLE>
<table>
<tr>
<td align="right">
 <input type="button" value="Add More Passenger" onclick="addMorePassengerRow('pdTable')"/>
 </td>
</tr>
<tr>
 <td align="center">
 <s:submit value="Book Ticket" align="center"/>
</td>
 </tr>
</table>
</s:form>
</body>
</html>

Deleting dynamically created rows :

This also can be done either by javascript code or Java code. In this example, I have used Java code to delete the row using row index.


public String delete()
 {

try {
 ticket=getTicket();
 passengerDetail=ticket.getPassengerDetail();
 passengerDetail.remove(getRowindex()); // removes the passenger object from the list based on the row index. 

 short sno=1;

// S.No is rearranged when a passenger row is deleted.

for (PassengerDetails p : passengerDetail)
 p.setSno(sno++);

 } catch (Exception e) {
 System.out.println(e.getMessage());
 e.printStackTrace();
 }

 return SUCCESS;

 }

The complete Action class is as follows. 


package net.javaonline.controller;
import java.util.ArrayList;
import java.util.List;
import net.javaonline.dto.PassengerDetails;
import net.javaonline.dto.Ticket;

import com.opensymphony.xwork2.ActionSupport;

public class TicketAction extends ActionSupport{

// public class Postings implements Action, ModelDriven<Ticket> {

 private Ticket ticket;
 private List<Ticket> ticketList;
 private List <PassengerDetails> passengerDetail;
 private int rowindex;

 public int getRowindex() {
 return rowindex;
 }

public void setRowindex(int rowindex) {
 this.rowindex = rowindex;
 }

private PassengerDetails passgr_Det;

public PassengerDetails getPassgr_Det() {
 return passgr_Det;
 }

public void setPassgr_Det(PassengerDetails passgr_Det) {
 this.passgr_Det = passgr_Det;
 }

public List<PassengerDetails> getPassengerDetail() {
 return passengerDetail;
 }

public void setPassengerDetail(List<PassengerDetails> passengerDetail) {
 this.passengerDetail = passengerDetail;
 }

public Ticket getTicket() {
 return ticket;
 }

public void setTicket(Ticket ticket) {
 this.ticket = ticket;
 }

 // to add a first blank row 

 public String execute() {
 ticket=new Ticket();
 List<PassengerDetails> pds=new ArrayList();
 passgr_Det=new PassengerDetails();
 passgr_Det.setSno((short)1);
 passgr_Det.setName("");
 passgr_Det.setGender("");
 passgr_Det.setAge("");
 pds.add(passgr_Det);
 ticket.setPassengerDetail(pds);
 ticket.setBusNo("7261");

 return SUCCESS;
 }

 public String delete()
 {

try {
 ticket=getTicket();
 passengerDetail=ticket.getPassengerDetail();
 passengerDetail.remove(getId());

 short sno=1;
 for (PassengerDetails p : passengerDetail)
 p.setSno(sno++);

 } catch (Exception e) {
 System.out.println(e.getMessage());
 e.printStackTrace();
 }

 return SUCCESS;
 }

 public String ticketBook() {
 try {
 ticket=getTicket();
 double totalFare=0.0;
 ticket.setBookedOn(new java.util.Date()); // for current date to store on createdOn field.
 passengerDetail=ticket.getPassengerDetail();

System.out.println("S.No Name Gender Age");

//For printing the passengers
 for (PassengerDetails p : passengerDetail) {
 System.out.print(p.getSno());
 System.out.print(p.getName());
 System.out.print(p.getGender());
 System.out.println(p.getAge());

 }

 totalFare=ticket.getFare()*passengerDetail.size();
 ticket.setTotalFare(totalFare);

 } catch (Exception e) {
 e.printStackTrace();
 }
 return SUCCESS;
 }

public List<Ticket> getTicketList() {
 return ticketList;
 }

 public void setTicketList(List<Ticket> ticketList) {
 this.ticketList = ticketList;
 }

 public Ticket getModel()
 {
 return ticket;
 }

}

Ack.jsp // Jsp code to disapy the Journey details with passenger list after successful submission.


<%@ page contentType="text/html; charset=UTF-8"%>
<%@ 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>Ticket Itinerary</title>
</head>
<body>
<h2>Ticket Itinerary</h2>
<div align="left">Your Ticket is booked with the following details.</div>
<table border="1">
<tr>
<td colspan=2>Journey Date : <s:property value="ticket.journeyDate"/></td>
<td colspan=2>Booking Date : <s:property value="ticket.bookedOn"/></td>
</tr>
<tr>
<td colspan=2>Bus Number : <s:property value="ticket.busNo"/></td>
<td colspan=2>Bus Name : <s:property value="ticket.busName"/></td>
</tr>

<tr>
<td colspan=2>From Station : <s:property value="ticket.fromStation"/></td>
<td colspan=2>To Station : <s:property value="ticket.toStation"/></td>
</tr>
<tr>
<td colspan=2>Fare : <s:property value="ticket.fare"/></td>
<td colspan=2>Total Fare : <s:property value="ticket.totalFare"/></td>
</tr>

<tr>
<td colspan=4 align="center">
<h5>Passenger Details</h5>
</td>
</tr>

<TR>
 <TD>S.No.</TD>
 <TD>Name</TD>
 <TD>Gender</TD>
 <TD>Age</TD>
 </TR>

<s:iterator value="ticket.PassengerDetail" var="tickets">
 <tr>
 <td><s:property value="sno"/></td>
 <td><s:property value="name"/></td>
 <td><s:property value="gender"/></td>
 <td><s:property value="age"/></td>
 </tr>
</s:iterator>
</table>
</body>
</html>

struts.xml

</p>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//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="false" />

<package name="default" extends="struts-default" namespace="/">

<action name="ticketBook"
class="net.javaonline.controller.TicketAction" method="ticketBook">
<result name="success">/Ack.jsp</result>
<result name="input">/TicketBook.jsp</result>
</action>

<action name="delete"
class="net.javaonline.controller.TicketAction" method="delete">
<result name="success">/TicketBook.jsp</result>
<result name="input">/TicketBook.jsp</result>
</action>
<action name="TicketAction" class="net.javaonline.controller.TicketAction">
<result name="input">/TicketBook.jsp</result>
<result name="success">/TicketBook.jsp</result>
</action>

</package>

</struts>
<p style="text-align: justify;">

Running  the above application,  by calling the url

http://localhost:8080/Structs2Dynamic/TicketAction.action   will give the below screen (one blank row for passenger details)

struts 2 dynamic design with one row

 

Three passengers are added dynamically. 

 

 

ticket booking

 

You can remove any passenger by clicking delete link.

Acknowledgement  (Ticket)

 

 

 

ticket booking ack

This project structure on eclipse looks like. 

struts2 dynamic structure

If you are new to struts 2, you can visit my earlier tutorial to configure and create a struts 2 sample application.

You may also like

Leave a Reply

7 Comments on "Struts 2 Adding / Removing Dynamic rows and getting values in struts 2 action."


Guest
vivek
5 months 6 days ago

I want to do the same thing with struts 1. How can i do this as there is no status attribut in iterator tag in struts 1?

Guest
zami
6 months 20 days ago

hello if u r adding rows dynamically via JAVA code then how does the JSP look like. Coz on click of add more passengers u r able to include a row in the screen ryt? then how will u do this wen u ryt the function using JAVA. I dont get it. Because am doing a similar kind of tool . Please can u clarify me

Guest
prajakta nikhare
7 months 19 days ago

can you please tell how to use custome template with struts textfield ?…

Guest
Chaitra
1 year 3 months ago

Hi VK, please let me know if the same can be implemented for Radio options

Guest
swati
4 months 7 days ago

hi… please let me knw if same can be implemente for radio optionss