Getting spring model attribute list item using index from javascript

Sorry if this was asked elsewhere, but I looked around, found a few answers, but not a complete example, and I still doubt it.

So, I am adding an autopopulation list from my Spring controller to my jsp, and I would like to add elements to the list inside my javascript / jquery function. Is it possible?

I tried the code below to test the functionality, but it didn’t work (list items did not display at all in the generated html). So I'm not sure if Im messed up the syntax of javascrit / spring / jsp or if it's just not possible.

Here is the code:

Controller Code:

@RequestMapping(value="/create_custobject.html",method = RequestMethod.GET) public ModelAndView showCreateCustObjectPage() { Map<String, Object> model = new HashMap<String, Object>(); CreateObjectForm form = new CreateObjectForm(); model.put("createObjectform", form); return new ModelAndView("create_custobject", model) ; } 

Form Code:

 public class CreateObjectForm { private AutoPopulatingList<Criteria> ruleArray = new AutoPopulatingList<Criteria>(Criteria.class); public AutoPopulatingList<Criteria> getRuleArray() { return ruleArray; } public void setRuleArray(AutoPopulatingList<Criteria> ruleArray) { this.ruleArray = ruleArray; } public CreateObjectForm() {} } 

Criteria:

 public class Criteria{ String attribute; String operator; //... constructor + getters and setters } 

javascript / jquery code (on the same page as jsp one):

 <script type="text/javascript"> $(document).ready(function(){ //startup functionality var i = 0; document.getElementById("addCriteria").onclick = function() { $("#msgid").html("${ruleArray[i].attribute}"); ${ruleArray[i].attribute} = $('#attributeValue').val(); ${ruleArray[i].operator} = $('#operatorValue').val(); i++; } } 
+1
source share
4 answers

for existing elements in your form use jstl like

 <c:forEach items="${form.items}" var="item" varStatus="status" > <span class="count" > <form:input path="items[${status.index}].field" /> 

it will look like this:

 <form id = "idform" > <span class="count" > <input name="items[0].field" id="items0.field" /> </span> </form> 

then you just use javascript to add a new “string” form with the corresponding indexes

eg

  var is = $('.count').size() $('#idform span:last').after('<span class="count" ><input name="items[' + is + '].field"' + is + '.field" /></span>') 

I think that if you use spring 3+, you do not need to use AutopopulatingList, any collection should be enough.

+3
source

Your JSP JSP and Javascript is wrong. You cannot use var i in a JSP expression, i.e. ${ruleArray[i].operator} . I would recommend using JSTL to iterate through the list and create your attributes in a script.

At this point, your script can be customized to just use the string literal 0 inside the expression. I assume that you need more robust functionality than that, can you describe it better.

 $(document).ready(function(){ document.getElementById("addCriteria").onclick = function() { $("#msgid").html("${ruleArray[0].attribute}"); //I assume you wanted to set the element to the value pulled from JSP EL $('#attributeValue').val(${ruleArray[0].attribute}); $('#operatorValue').val(${ruleArray[0].operator}); } } 

Using a JSTL solution would look something like this:

 <script> var criteria = []; <c:forEach var="criteria" items=${ruleArray}> criteria.push({attr:${criteria.attribute}, oper: ${criteria.operator}); </c:forEach> for(var i = 0; i < criteria.length; i++){ alert(criteria[i].attribute); } </script> 

This solution mainly uses JSTL to write Javascript. This might be the best solution to modify your controller to return JSON and just make an Ajax call when the page loads.

+1
source

in the next line, you are referencing i in the jsp code, but I am not defined:

 $("#msgid").html("${ruleArray[i].attribute}"); 

The javascript code that defines i is executed on the client (i.e. in the browser). Jsp code is executed on the server until the rendered html is sent to the client.

0
source

Despite the fact that this branch is older and the correct answer is given, for the benefit of beginners, as well as to explain the logic of deleting added lines.

Let me explain with a minimal code and example user with fields firstName, email, userName and gender.
Given that you send 3 empty users to usersList from the controller, this will create 3 empty lines. And now you want to add lines and dynamically link the added lines with modelAttribute.

(in the case of the initial 3 lines) If you inspect / view the source code of the 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 to help 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

All Articles