I'm new to Spring and little confused of how to use beans for populating and retrieving values to/from the view.
Here is what I'm doing now.
In the controller I'm initializing two beans xxxMain.java and xxxView.java. I'm using xxxMain.java to retrieve values FROM the view and xxxView.java for pre-populating the view.
Here is my controller
#RequestMapping(value = "accounting", method = RequestMethod.GET)
public String showPage( Model model) {
XXXMain xxxMain = new XXXMain();
XXXView xxxView = new XXXView();
service.loadXXXForm(xxxMain, xxxView);
model.addAttribute("xxxMain", xxxMain);
model.addAttribute("xxxView", xxxView);
return "admin/xxx";
}
So as I'm using the xxxMain.java for retrieving I'm coding the jsp like this.
<form:form modelAttribute="XXXMain" method="post" action="/app/home/save">
</form:form>
also I'm using Spring tags, like
<form:input path="name" size="15"/>
Now, when the fields in the view are empty, all is fine, but when I have to pre-populate the fields, I'm not sure what approach to take as
<form:input path="name" size="15"/>
does not has a value attribute to populate the field. So what I have done is populate the XXXMain.java class along with the XXXView.java class with the default values, as you can see in the controller code snippet. That way values are pre-populated when view is first loaded. But I'm not sure if I'm doing the right thing by populating the xxxMain.java file which in fact should only contain the user entered values.
How can I improve this design?
Thanks a lot.
Ravi
Here is an example I wrote which might help steer you right.
Related
I have a form and post data into controller via Thymeleaf:
<form action="lia.html" th:action="#{/lia}" th:object="${myRequest}" method="post">
At another place of my html page, if a user click a particular button, I want to modify that object and send it to same controller.
I have already that object which has been initialised. Button is not a part of any form. How can I send that object into a controller with Thymeleaf.
PS: I know that I can send it via Javascript or put such buttons into a form but I want to learn the Thymeleaf way.
I think the only similar approach to what you're looking for is using bind with Spring EL expressions.
Thanks to the advanced form-field binding capabilities in Spring MVC,
we can use complex Spring EL expressions to bind dynamic form fields
to our form-backing bean. This will allow us to create new Row objects
in our SeedStarter bean, and to add those rows’ fields to our form at
user request.
Take a look the next link, where is good example:
http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dynamic-fields
The button
<button type="submit" name="removeRow"
th:value="${rowStat.index}" th:text="#{seedstarter.row.remove}">Remove row</button>
Request Mapping
#RequestMapping(value="/seedstartermng", params={"removeRow"})
public String removeRow(
final SeedStarter seedStarter, final BindingResult bindingResult,
final HttpServletRequest req) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
seedStarter.getRows().remove(rowId.intValue());
return "seedstartermng";
}
This is an add page. Person contains a list of addresses so when i try to add an address to that person that is not yet in the database i need to be able to retrieve the person form when an address is submitted and assign that address to that person.
<form:form action="${addAction}" modelAttribute="person">
<form:label path="name">
<spring:message text="Name"/>
</form:label>
<form:input path="name" />
... More labels and inputs
</form:form>
<form:form action="${addAddress}" modelAttribute="address">
... Labels
<input type="submit" value="<spring:message text="Add Address"/>" />
</form:form>
In my controller i have "#ModelAttribute("person") Person p" line which should retrieve the form which has "modelAttribute="person"" in it. But the person retrieved is an empty entity which i'm assuming is because the person form has to be submitted in order to retrieve the data.
#RequestMapping(value = "/person/addAddress", method = RequestMethod.POST)
public String addAddress(#ModelAttribute("person") Person p, #ModelAttribute("address") Address a, RedirectAttributes redirectAttrs) {
p.getAddresses().add(a);
redirectAttrs.addFlashAttribute("person", p);
return "redirect:/person";
}
I probably can retrieve the inputs instead of the form and use them to create a new entity with those values but if i were to do that controllers' passing attributes will be full of inputs and would look ugly. Is there a way for me to retrieve those values as a Person entity?
EDIT
Sanjay's first option is the most logical way to do it but since what i wanted to design does not fit for it i can't do it. But Sanjay's comment about making it in one form helped me so i'm selecting Sanjay's answer as the solution but here is how i fixed it
Since i had form actions saved in c:url's i changed the buttons' onclick function such that when clicked forms' action would change depending on the button and i already had corresponding controllers for the actions. For the address list inside my person i had to make a workaround by first adding an empty address to the list in my page controller and then using
<c:forEach items="${person.addresses}" varStatus="loop">
<c:if test="${loop.last}">
<form:input path="addresses[${loop.index}].street" />
...
the code above i was able to fill the previously added empty address.
I'm still in the process of fixing everything but this is the general idea of how i fixed it. Thanks for the help.
I think you may need to revisit your UI, add some hidden field etc. I can think of some solutions:
Have an "Add Address" button which appends a blank row of address into the form using JavaScript, but it doesn't submit to the server. Have the real "Submit" button at the bottom, which would submit the entire form including the person and addresses.
Have a submit button to save the person without address. Then, on a second screen, display the person, and have the address submission button.
Do the above, in reverse, if saving the Address first suits your requirements
I probably can retreieve the inputs instead of the form and use them to create a new entity with those values but if i were to do that controllers' passing attributes will be full of inputs and would look ugly. Is there a way for me to retrieve those values as a Person entity?
For cleaner code -
1.Create JSON object (say formFields) with all your form input data.
2.send formFields to server using ajax call.
3.Read formFields as String in controller
#ModelAttribute("formFields") final String formFields
4.You should have DTO matching formFields name say FormDTO.
5.convert formFields of String type to FormDTO using ObjectMapper API.
FormDTO formDto = null;
try {
ObjectMapper mapper = new ObjectMapper();
formDto = mapper.readValue(formDto, FormDTO.class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
P.S. ObjectMapper is part of jackson-databind-2.4.4.jar
I am trying to modify and send a list of objects using spring MVC.
I want , when I will click in the button that triggers the form submit, in the controller, capture all the list with the objects.
Unfortunately.. I have no idea how to do this.
So far I got this:
<#form:form modelAttribute="MyObject" method="post" action"somewhere">
<#display:table list=myList id="myObject">
<#display.column title="Name">
${myObject.name}
</#display>
<#display.column title="value">
HERE I SHOULD MODIFY EVERY OBJECT WITH AN INPUT, NOT SURE IF THIS WOULD WORK
<form:input path=${myObject.value} id="value" />
</#display>
</#display>
</#form:form>
And at my controller so far I have this:
#RequestMapping (value="myurl" method = Request.POST)
public void myMethod(#ModelAttribute Object myObjects){
So here Id like to get the entire list of objects, but myObjects is null.
}
Any idea how to do this?
Thanks
I have checkboxes tag in my web application with spring mvc. Checkboxes are created from a map in controller like this:
Map demOrgs = createMap();
model.addAttribute("demOrgs", demOrgs); // example : (1, my-description)
1 --> will be value of checkbox
my-description --> will be label of checkbox
In my jsp :
<form:form commandName="myBean" method="POST" >
<form:checkboxes items="${demOrgs}" path="demOrg" element='div class="checkboxes"' />
</form:form>
My bean has only one field :
String demOrg;
When I send the form demOrg attribute has the value of checkboxes clicked, for example: (1,5,8)
I store myBean in session, when I go to the next step in my application. But when I return, I want the checkboxes were checked, still checked and isn't that way.
When the bind value of checkbox is a boolean value, allways work but I'm binding a custom value :
<input id="demOrg1" type="checkbox" value="2" name="demOrg">
<label for="demOrg1">My label description</label>
<input id="demOrg2" type="checkbox" value="3" name="demOrg">
<label for="demOrg2">My label description 2</label>
.....
Does anyone know how to do this?
thanks to all!!
What does the signature of your controller method look like? Are you including myBean as a method signature argument, annotated with #ModelAttribute ?
Something like:
#RequestMapping(......)
public String myController (#ModelAttribute MyBeanType myBean, Model model) {
Map demOrgs = createMap();
model.addAttribute("demOrgs", demOrgs);
model.addAttribute(myBean);
}
Optionally you can annotate the method parameter with #Valid as well if you are using JSR-303 bean validation .
I think the trick is to make sure your demOrg property is actually a collection. Check out the
checkbox reference here. In particular, the text that says:
Typically the bound property is a collection so it can hold multiple values selected by the user.
Though "myBean" is stored in the session, isn't it reloaded again from the database when the controller is ran?
I have not been able to find a solution on this yet after searching and searching.
Using Spring 3.1
I have a form where I would like the user to be able to add multiple point of contacts (poc). In my JSP I have a submit button for adding a poc. It goes to a Spring Controller, gets the current list of pocs from the domain object (which will be empty at first), adds the poc to the list and then puts the domain object back into the model before returning to the same view. Then the user will ultimately submit the entire page which will go to the controller and save the entire object to persistence.
I have tried various attempts and come up with different results from only being able to add one poc with a new one overwriting the existing, to not being able to get the entered poc displayed on the form. I will put the code I currently have.
JSP:
<form:form method="post" commandName="request">
...
<h2>POC:</h2>
<input type="text" name="newPoc"/>
<input type="submit" name="addPoc" value="Add POC"/>
<table>
...
<c:forEach items="${request.pointOfContacts}" var="poc" varStatus="vs">
<tr>
<td><form:label path="pointOfContacts[${vs.index}].name/></td>
.....
</c:forEach>
......
</table>
</form:form>
Spring Controller:
#RequestMapping(value="/request", method=RequestMethod.POST, param="addPoc")
public Sring addPoc(#RequestParam String newPoc, MyRequest req, Model model) {
PointOfContact poc = new PointOfContact();
poc.setName(newPoc);
List<PointOfContact> pocs = req.getPointOfContacts();
pocs.add(poc);
req.setPointOfContacts(pocs);
model.addAttribute("request", req);
return "requestForm";
}
Domain Objects
#Entity
public class MyRequest {
...
#OneToMany(Cascade=CascadeType.ALL)
private List<PointOfContact> pointOfContacts = new ArrayList<PointOfContact>();
.....
}
#Entity
public class PointOfContact {
...
private String name;
....
}
Does anybody have any solutions? I have seen various posts about AutoPopulatingList, is this a solution? If so how would I use it in this example.
Yes you should use AutoPopulatingList, example. This will require change in MyRequest entity.