Add rows to the table at the click of a button using spring MVC, and associate the added rows with modelAttribute.

I have a table for which I pass a list of student objects from my spring controller method. 3 rows are loaded on the page. I want the user to be able to add more rows by deleting existing rows when the button is clicked. Can anyone tell me how to achieve this. See below my controller and jsp code. When I click the Add button, I want to add another 3 lines by selecting the checkbox, and clicking the Delete button should delete the line. I want added columns to be anchored

I am very new to jQuery, this is possible without jQuery. If not, tell me in detail how to do this using jQuery

My table snap shot

Student entity

@Entity @Table(name="STUDENT_REGISTRATION") public class Student { private int studentId; private String firstName; private String lastName; private Date dob; private String sex; private String status; private Date doj; private int deptId; private String deptName; private int batchId; private String batchName; private int roleId; private String roleName; private String regNo; public Student(){ } public Student(int studentId, String firstName, String lastName, Date dob, String sex, String status, Date doj, int deptId, String deptName, int batchId, String batchName, int roleId, String roleName, String regNo) { super(); this.studentId = studentId; this.firstName = firstName; this.lastName = lastName; this.dob = dob; this.sex = sex; this.status = status; this.doj = doj; this.deptId = deptId; this.deptName = deptName; this.batchId = batchId; this.batchName = batchName; this.roleId = roleId; this.roleName = roleName; this.regNo = regNo; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="STUDENT_ID") public int getStudentId() { return studentId; } public void setStudentId(int studentId) { this.studentId = studentId; } @Column(name="STUDENT_FIRST_NAME") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @Column(name="STUDENT_LAST_NAME") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Column(name="DOB") public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } @Column(name="SEX") public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Column(name="STATUS") public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } @Column(name="DOJ") public Date getDoj() { return doj; } public void setDoj(Date doj) { this.doj = doj; } @Column(name="DEPT_ID") public int getDeptId() { return deptId; } public void setDeptId(int deptId) { this.deptId = deptId; } @Column(name="DEPT_NAME") public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } @Column(name="BATCH_ID") public int getBatchId() { return batchId; } public void setBatchId(int batchId) { this.batchId = batchId; } @Column(name="BATCH_NAME") public String getBatchName() { return batchName; } public void setBatchName(String batchName) { this.batchName = batchName; } @Column(name="ROLE_ID") public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } @Column(name="ROLE_NAME") public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } @Column(name="REG_NO") public String getRegNo() { return regNo; } public void setRegNo(String regNo) { this.regNo = regNo; } } 

DTO student

 public class StudentDTO { private int studentId; private String firstName; private String lastName; private Date dob; private String sex; private String status; private Date doj; private int deptId; private String deptName; private int batchId; private String batchName; private int roleId; private String roleName; boolean select; private String regNo; public StudentDTO(){ } public StudentDTO(int studentId, String firstName, String lastName, Date dob, String sex, String status, Date doj, int deptId, String deptName, int batchId, String batchName, int roleId, String roleName, boolean select, String regNo) { super(); this.studentId = studentId; this.firstName = firstName; this.lastName = lastName; this.dob = dob; this.sex = sex; this.status = status; this.doj = doj; this.deptId = deptId; this.deptName = deptName; this.batchId = batchId; this.batchName = batchName; this.roleId = roleId; this.roleName = roleName; this.select = select; this.regNo = regNo; } public int getStudentId() { return studentId; } public void setStudentId(int studentId) { this.studentId = studentId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Date getDoj() { return doj; } public void setDoj(Date doj) { this.doj = doj; } public int getDeptId() { return deptId; } public void setDeptId(int deptId) { this.deptId = deptId; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public int getBatchId() { return batchId; } public void setBatchId(int batchId) { this.batchId = batchId; } public String getBatchName() { return batchName; } public void setBatchName(String batchName) { this.batchName = batchName; } public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public boolean isSelect() { return select; } public void setSelect(boolean select) { this.select = select; } public String getRegNo() { return regNo; } public void setRegNo(String regNo) { this.regNo = regNo; } } 

Here I add 3 student objects

  public List<StudentDTO> addStudentToList(){ List<StudentDTO> studentList = new ArrayList<StudentDTO>(); StudentDTO stud = new StudentDTO(); for(int i=0; i<3; i++){ studentList.add(stud); } return studentList; } Student Controller class @RequestMapping(value="/addStudent", method=RequestMethod.GET) public ModelAndView getStudentForm(ModelMap model) { List<StudentDTO> studentList = studentService.getStudentAttributesList(); //List<Integer> userIdForDropDown = userDAO.getAllUserIdForDropDown(); //model.addAttribute("userIdDropDown",userIdForDropDown); List<String> deptList = configDAO.getDeptListForDropDown(); model.addAttribute("deptlist",deptList); List<String> batchList = configDAO.getAllBatchForDropDrown(); model.addAttribute("batchList", batchList); ModelAndView mav = new ModelAndView("add_student"); Student stu = new Student(); mav.getModelMap().put("add_student", stu); StudentForm studentForm = new StudentForm(); studentForm.setStudentList(studentList); model.addAttribute("studentForm",studentForm); return mav; } @RequestMapping(value="/addStudent", method=RequestMethod.POST) public String saveStudent(@ModelAttribute("add_student") StudentForm studenfForm, BindingResult result, SessionStatus status, ModelMap model) throws ParseException{ /*if(result.hasErrors()){ return "add_student"; }*/ List<StudentDTO> newList = (List<StudentDTO>) studenfForm.getStudentList(); List<Student> newList1 = new ArrayList<Student>(); for(StudentDTO stud:studenfForm.getStudentList()){ Student student = new Student(); student.setBatchId(stud.getBatchId()); student.setBatchName(stud.getBatchName()); student.setDeptId(stud.getDeptId()); student.setDeptName(stud.getDeptName()); SimpleDateFormat sdf = new SimpleDateFormat("DD/MM/YYYY"); Date dateWithoutTime = sdf.parse(sdf.format(new Date())); student.setDob(stud.getDob()); student.setDoj(stud.getDoj()); student.setFirstName(stud.getFirstName()); student.setLastName(stud.getLastName()); student.setRegNo(stud.getRegNo()); student.setRoleId(stud.getRoleId()); student.setRoleName(stud.getRoleName()); student.setStatus(stud.getStatus()); student.setSex(stud.getSex()); student.setStudentId(stud.getStudentId()); newList1.add(student); } Integer saveStatus = studentDAO.saveStudentInfo(newList1); //Integer res = roleDAO.saveRole(role); if(saveStatus!=null){ status.setComplete(); model.addAttribute("savedMsg", "Student record saved Successfully."); } return "redirect:addStudent"; } 

See my jsp page

 <table bgcolor="white" width="1200" height="300" align="center" style="border-collapse: collapse;" border="1" bordercolor="#006699" > <form:form action="addStudent" method="post" commandName="add_student" modelAttribute="studentForm"> <tr> <td align="center" style="background-color: lightblue"><h3>Add Student</h3></td> </tr> <tr align="left"> <td align="left"> <input type="button" id="addrows" name="addrows" class="addperson" value="Add Rows"> <input type="button" id="removerows" class="removerows" value="Delete Rows" /> <input type="submit" value="Save" /> </td> </tr> <tr valign="middle" align="center"> <td align="center" valign="middle"> <table width="1200" height="200" style="border-collapse: collapse;" border="0" bordercolor="#006699" cellspacing="0" cellpadding="0"> <thead> <tr height="1" bgcolor="lightblue"> <th colspan="1"> No </th> <th width="5"> Select </th> <th> Reg No </th> <th> First Name </th> <th> Last Name </th> <th> Sex </th> <th> DOB </th> <th> DOJ </th> <th> Dept Name </th> <th> Role Name </th> <th> Batch Name </th> <th> Status </th> </tr> </thead> <tbody> <c:forEach var="rows" items="${studentForm.studentList}" varStatus="status"> <tr class="${status.index % 2 == 0 ? 'even' : 'odd'}" > <td width="15"> <b>${status.count}</b> </td> <td width="10"> <form:checkbox path="studentList[${status.index}].select"/> </td> <td><form:input path="studentList[${status.index}].regNo"/></td> <td><form:input path="studentList[${status.index}].firstName"/></td> <td><form:input path="studentList[${status.index}].lastName"/></td> <td><form:select path="studentList[${status.index}].sex"> <form:option value="NONE" label="--- Select ---"/> <form:option value="M" label="Male"/> <form:option value="F" label="Female"/> </form:select></td> <td><form:input path="studentList[${status.index}].dob"/></td> <td><form:input path="studentList[${status.index}].doj"/></td> <td><form:select path="studentList[${status.index}].deptName"> <form:option value="NONE" label="--- Select ---"/> <form:options items="${deptlist}" /> </form:select></td> <td><form:select path="studentList[${status.index}].roleName"> <form:option value="NONE" label="--- Select ---"/> <form:option value="ROLE_STUDENT" label="Student"/> <form:option value="ROLE_BATCHREP" label="Batch Rep"/> </form:select></td> <td><form:select path="studentList[${status.index}].batchName"> <form:option value="NONE" label="--- Select ---"/> <form:options items="${batchList}" /> </form:select> </td> <td><form:select path="studentList[${status.index}].status"> <form:option value="NONE" label="--- Select ---"/> <form:option value="E" label="Enable"/> <form:option value="D" label="Disable"/> </form:select></td> </tr> </c:forEach> </tbody> </table> </td> </tr> <tr align="center"> <td width="100" align="center"><B> ${savedMsg} </B> </td> </tr> </form:form> </table> 
+9
source share
2 answers

Despite the fact that this branch is older, for the benefit of others who need it.

Let me explain with a minimal code and an example user with the fields firstName, email, userName and gender so that people do not get confused with the big code.
Suppose you send 3 empty users to usersList from the controller, this will create 3 empty lines. If you browse / browse the source page, you will see

  • Lines ( <input> tags ) with a different identifier , like list0.firstName list1.firstName
  • Strings ( <input> tags ) with different names , for example list[0].firstName list[1].firstName

Whenever a form is submitted, id's are not considered by the server (they are added only for assistance with client-side validation), but the name attribute will be interpreted as a request parameter and used to create your modelAttribute, therefore, attribute names are very important when inserting strings.

Adding a line

So how to build / add new lines?
If I send 6 users from the user interface, the controller should get 6 user objects from the user list. The steps to achieve the same are given below.
1. Right-click -> view page source . You will see such lines (you can see *[0].* In the first row and *[1].* In the second row)

 <tr> <td><input id="list0.firstName" name="list[0].firstName" type="text" value=""/></td> <td><input id="list0.email" name="list[0].email" type="text" value=""/></td> <td><input id="list0.userName" name="list[0].userName" type="text" value=""/></td> <td> <span> <input id="list0.gender1" name="list[0].gender" type="radio" value="MALE" checked="checked"/>Male </span> <span> <input id="list0.gender2" name="list[0].gender" type="radio" value="FEMALE"/>Female </span> </td> </tr> <tr> <td><input id="list1.firstName" name="list[1].firstName" type="text" value=""/></td> <td><input id="list1.email" name="list[1].email" type="text" value=""/></td> <td><input id="list1.userName" name="list[1].userName" type="text" value=""/></td> <td> <span> <input id="list1.gender1" name="list[1].gender" type="radio" value="MALE" checked="checked"/>Male </span> <span> <input id="list1.gender2" name="list[1].gender" type="radio" value="FEMALE"/>Female </span> </td> </tr> 
  1. Copy the first line and create a javascript line and replace '0' with the variable name index. As indicated in the example below
 '<tr>'+ '<td><input id="list'+ index +'.firstName" name="list['+ index +'].firstName" type="text" value=""/></td>'+ '<td><input id="list'+ index +'.email" name="list['+ index +'].email" type="text" value=""/></td>'+ ... '</tr>'; 
  1. Add the constructed string to the <tbody> . Lines are also added to the user interface when the form is submitted; new added lines will be received in the controller.

Delete row

Deleting a line is a bit more complicated, I will try to explain the easiest

  • Suppose you add row0, row1, row2, row3, row4, row5
  • Deleted row2, row3. Not just hide the line, but remove it from the DOM, catching the event.
  • Now row0, row1, row4, row5 will be sent, but in your controller userList will have 6 user objects, but user [2] .firstName will be zero and user [3] .firstName will be zero.
  • So in your iteration controller and check for a null value and delete the user. (Use an iterator, do not use foreach to delete a user object)

Posting code for beginners.

 // In Controller @RequestMapping(value = "/app/admin/add-users", method = RequestMethod.GET) public String addUsers(Model model, HttpServletRequest request) { List<DbUserDetails> usersList = new ArrayList<>(); ListWrapper userListWrapper = new ListWrapper(); userListWrapper.setList(usersList); DbUserDetails user; for(int i=0; i<3;i++) { user = new DbUserDetails(); user.setGender("MALE"); //Initialization of Radio button/ Checkboxes/ Dropdowns usersList.add(user); } model.addAttribute("userListWrapper", userListWrapper); model.addAttribute("roleList", roleList); return "add-users"; } @RequestMapping(value = "/app/admin/add-users", method = RequestMethod.POST) public String saveUsers(@ModelAttribute("userListWrapper") ListWrapper userListWrapper, Model model, HttpServletRequest request) { List<DbUserDetails> usersList = userListWrapper.getList(); Iterator<DbUserDetails> itr = usersList.iterator(); while(itr.hasNext()) { if(itr.next().getFirstName() == null) { itr.remove(); } } userListWrapper.getList().forEach(user -> { System.out.println(user.getFirstName()); }); return "add-users"; } //POJO @Entity @Table(name = "userdetails") @XmlRootElement(name = "user") public class DbUserDetails implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String firstName; private String userName; private String email; private String gender; //setters and getters } //list wrapper public class ListWrapper { private List<DbUserDetails> list; //setters and getters } 

In jsp

 <form:form method="post" action="${pageContext.request.contextPath}/app/admin/add-users" modelAttribute="userListWrapper"> <table class="table table-bordered"> <thead> <tr> <th><spring:message code="app.userform.firstname.label"/></th> <th><spring:message code="app.userform.email.label"/></th> <th><spring:message code="app.userform.username.label"/></th> <th><spring:message code="app.userform.gender.label"/></th> </tr> </thead> <tbody id="tbodyContainer"> <c:forEach items="${userListWrapper.list}" var="user" varStatus="loop"> <tr> <td><form:input path="list[${loop.index}].firstName" /></td> <td><form:input path="list[${loop.index}].email" /></td> <td><form:input path="list[${loop.index}].userName" /></td> <td> <span> <form:radiobutton path="list[${loop.index}].gender" value="MALE" /><spring:message code="app.userform.gender.male.label"/> </span> <span> <form:radiobutton path="list[${loop.index}].gender" value="FEMALE" /><spring:message code="app.userform.gender.female.label"/> </span> </td> </tr> </c:forEach> </tbody> </table> <div class="offset-11 col-md-1"> <button type="submit" class="btn btn-primary">SAVE ALL</button> </div> </form:form> 

Javascript must be included in JSP

 var currentIndex = 3; //equals to initialRow (Rows shown on page load) function addRow() { var rowConstructed = constructRow(currentIndex++); $("#tbodyContainer").append(rowConstructed); } function constructRow(index) { return '<tr>'+ '<td><input id="list'+ index +'.firstName" name="list['+ index +'].firstName" type="text" value=""/></td>'+ '<td><input id="list'+ index +'.email" name="list['+ index +'].email" type="text" value=""/></td>'+ '<td><input id="list'+ index +'.userName" name="list['+ index +'].userName" type="text" value=""/></td>'+ '<td>'+ '<span>'+ '<input id="list'+ index +'.gender1" name="list['+ index +'].gender" type="radio" value="MALE" checked="checked"/>Male'+ '</span>'+ '<span>'+ '<input id="list'+ index +'.gender'+ index +'" name="list['+ index +'].gender" type="radio" value="FEMALE"/>Female'+ '</span>'+ '</td>'+ '</tr>'; } 
0
source

If your problem is with automatic data binding, this may help http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/

grails internally uses spring mvc, so the same approach would work here too

-1
source

All Articles