Spring - form with 2 modelAttributes - spring

I know how to use a form with 1 modelAttribute but how should I set 2 model attributes in same form ?
I have:
<sf:form id="details" action="/updateuser" method="POST" modelAttribute="updateuser">
<sf:input type="text" name="firstName" path="firstName"/></br>
<sf:input type="text" name="lastName" path="lastName" /></br>
<sf:input type="text" name="email" path="email" /><sf:errors path="email" cssClass="error"></sf:errors> </br>
<sf:input type="text" name="facebook" path="facebook" /> </br>
<sf:input type="text" name="twitter" path="twitter" /> </br>
</sf:form>
firstName lastName and email are for modelAttribute="updateuser" but I need another modelAttribute for facebook and twitter
How should I implement this ?
Thanks!
EDIT:
Isn't there any other way to do this without a wrapper class ? For more info, I have:
class User {
private String firstName;
private String lastName;
private String email;
}
class SocialMedia {
private String facebook;
private String twitter;
}

You can't attach more than one object to the <form>. However, you can create an explicit model class for the form and attach it.
class UpdateUserFormModel {
private Updateuser updateuser;
private Facebook facebook;
private Twitter twitter;
}
You can access nested objects using . operator
<sf:input type="text" name="firstName" path="updateuser.firstName"/></br>
<sf:input type="text" name="facebook" path="facebook" /> </br>

No you can't have more than one model attribute for one form, but you can use a wrapper to wrap your models.
class Wrapper {
private Class1 c1;
private Class2 c2;
....
//getter&setters
}
However, you are allowed to bind several objects to the same model using
model.addObject("objectName",object);
and access the objects in your page by
${objectName.name }

Related

How to handle forms mapped to more than one entity using Thymeleaf + Hibernate + Spring Boot?

I have a form in Thymeleaf that I want to link to two different entity to be persisted to the database using Hibernate
I have the following form using Thymeleaf:
<form th:action="#{/app/handleForm}" th:object="${entity1}"
method="post">
<input type="text" th:field="*{field1}" />
<input type="text" th:field="*{field2}" />
<input type="text" th:field="*{field3}" />
</form>
Let's supposea the first two fields are bound to entity1 and the third field to be bound to entity2 (not entity1) how should I do this?
Also, in the controller method, I have two DAO implementation for persisting them:
#PostMapping("app/handleForm")
public String RHTraiterDemande(Model m, Entity1 entity1, Entity2
entity2) {
entity1Service.add(entity1);
entity2Service.add(entity2);
return "showResults";
}
How to do this?
You could create a custom object with the required information and mapped it using th:object.
New Class
public class MyClass {
private Entity1 entity1;
private Entity2 entity2;
// Getters and setters.
}
Form
<form th:action="#{/app/handleForm}" th:object="${myClass}"
method="post">
<input type="text" th:field="*{entity1.field1}"/>
<input type="text" th:field="*{entity1.field2}"/>
<input type="text" th:field="*{entity2.field3}"/>
</form>
Controller
#PostMapping("app/handleForm")
public String RHTraiterDemande(Model m, MyClass myClass) {
entity1Service.add(myClass.entity1);
entity2Service.add(myClass.entity2);
return "showResults";
}

handle one to many relationship in thymeleaf using spring mvc

I'm having One entity as Vendor and Another as Address and the relationship between both of them is One To Many form Vendor to Address.
Note : I am using JPA
My Vendor Entity
public class Vendor {
private Integer id;
private String name;
private List<Address> address;
// getter and setters
}
Address class:
public class Address {
private Integer id;
private String addressline1;
private String addressline2;
//getter and setters
}
Now I am using Thymeleaf , I have a scenario where I need to add the address dynamically to a form for the particular vendor.
How do I do Object binding for the Address object in Vendor using Thymeleaf in spring mvc?
Comment if i didn't understand your question correct, it's a bit unclear to me...
In order to access the address(s) of a vendor, you provide a vendor within your controller (something like model.addAttribute("vendor", currentVendor);) and call vendor.address in your html file. Please note that this will give you a list so you need to iterate to show all address:
<tr th:each="address : ${vendor.address}">
<td th:text="${address.id}">1</td>
<td th:text="${address.addressline1}"></td>
<td th:text="${address.addressline2}"></td>
</tr>
Uhhh, that's tricky because binding to form doesn't work in a dynamic way. That means you can't do something like #Viergelenker suggests AND bind each address-object to his own form.
You can add a single address object to the model, e.g.
model.addAttribute("address", addressObject); // Snippet for Model-object
modelAndView.addObject("address", addressObject); // Snippet for ModelAndView object
and then define a form in yout template like:
<form .... method=".." th:object="${address}">
<input type="hidden" th:field="*{id}" >
<input type="text" th:field="*{addressline1}" >
<input type="text" th:field="*{addressline2}" >
</form>
Unfortunately it is not possible to add a array or list to the model and bind each object in that collection to his own form:
/* The following code doesn't work */
<th:block th:each="address : ${addresses}">
<form .... method=".." th:object="${address}">
<input type="text" th:field="*{addressline1}" >
...
</form>
</th:block>
or
/* The following code doesn't work */
<th:block th:each="address, stat : ${addresses}">
<form .... method=".." th:object="${addresses[__stat.index__]}">
<input type="text" th:field="*{addressline1}" >
...
</form>
</th:block>
What you can do is not to use form binding and just send some name-value pairs from forms without the binding (just use the name and the th:value attributes and not the th:field attribute in your forms) to the controller, get them there from the HttpServletRequest object and create/update/delete address-objects ... or bind the whole Vendor object to a form (note the use of stat.index):
<form th:object="${vendor}">
<input type="hidden" th:field="*{id}">
<input type="hidden" th:field="*{name}"> // feel free to make that field editable
<th:block th:each="addr, stat : *{address}">
<input type="hidden" th:field="*{address[__${stat.index}__].id}">
<input type="text" th:field="*{address[__${stat.index}__].addressline1}">
<input type="text" th:field="*{address[__${stat.index}__].addressline2}">
</th:block>
</form>

how to get form values to controller in spring mvc

I am trying to get form values from jsp to controller in spring mvc, but i am not able to get form data.
This is my DTO (bean)
public class LoginDTO implements Serializable {
private Long id;
private String username;
private String password;
// setter and getter methods
}
and my Jsp
<form class="form-signin" action="test" method="get" modelAttribute="userFormData">
<input type="text" class="form-control"
placeholder="Email" required autofocus>
<input type="password" class="form-control"
placeholder="Password" required>
<input class="btn btn-md btn-success btn-block"
type="submit" value="Signin">
</form>
and my controller
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result) {
System.out.println("Controller...");
System.out.println("=====> " + formData.getUsername());
System.out.println("=====> " + formData.getPassword());
}
Add names to the controls on your JSP pages.
<input type="text" name="username" ...>
<input type="password" name="password" ...>
To let spring understand which form control value should go to which property of the LoginDTO
we can also use the springframework has given us a form tags.so that we can also use that but in that case you have to define your the input path same as the member varibale given in your class.
like this
<form:form method="post" modelAttribute="userFormData">
<form:input path="username" />
<form:input path="password" />
Then in the controller you can write like this as you have written
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result)
In case you want to get the result on other jsp page as well as on console then do:
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result , Model model){
System.out.println("=====> " + formData.getUsername()); //this outputs username on console
System.out.println("=====> " + formData.getPassword()); //this outputs password on console
model.addAttribute("LoginDTO ", LoginDTO );
return "success"; //this is the return page where the username and password will be rendered as view
}

Spring 3 binding object to list

I think my syntax is correct, but the list in my form backing object is not getting populated. It looks like the list itself is being made, just that it has no elements. The other attributes are being populated as expected. Any ideas?
JSP:
<form:form method="post" commandName="addReminder">
Reminder Name <input type='text' name='reminderName' placeholder="Reminder Name"> <br />
Date <input type='text' name='date' placeholder="1/05/2013"> <br />
Time <input type='text' name='time' placeholder="4:00 PM"> <br />
Time Zone <input type='text' name='timeZone' placeholder="EDT"> <br />
<br />
Contacts <input type='text' path="contacts[0].phoneNumber" placeholder="Name"> <br />
<input type='text' path="contacts[1].phoneNumber" placeholder="Name"> <br />
<input type="submit" value = "Add Reminder">
</form:form>
Controller:
#RequestMapping(value = "/AddAReminder", method = RequestMethod.POST)
public String addReminder(#ModelAttribute("addReminder") AddReminder reminder, BindingResult result)
{
//does stuff with the data from the form backing object
return "Add A Reminder";
}
Form backing object:
public class AddReminder
{
private String reminderName;
private String date;
private String time;
private String timeZone;
private ArrayList<Contact> contacts = new ArrayList<Contact>();
private String sentFrom;
private String message;
private String provider;
//getters and setters
Contact object:
public class Contact
{
private String firstName;
private String lastName;
private String phoneNumber;
private String provider;
//getters and setters
you can use <c:forEach> as :
<form:form method="post" commandName="allProductEdit">
<c:forEach items="${allProductEdit.products}" var="prod" varStatus="pStatus">
<form:input path="products[${pStatus.index}].description" />
<form:input path="products[${pStatus.index}].price" />
</c:forEach>
<input type="submit" value="Execute">
</form:form>
check this forum link http://forum.springsource.org/showthread.php?54509-lt-form-input-gt-inside-lt-c-forEach-gt
Ok I figured out what change I made that got this working. I initialize the list with a Contact object on the GET request. I say initalize, but I mean I just add an element to the list so it isn't empty. The list itself is already initialized in the AddReminder class. Spring will then auto grow the list.

Model Binding collections in ASP.NET MVC with hidden controls

Hihi,
Having trouble model binding with this class (the following concrete, not the abstract).
Ignore the basic properties, its the Lists that I'm interested in binding.
public abstract class MessageModel
{
public string Tag { get; set; }
public string Message { get; set; }
public int Id { get; set; }
public const int DefaultIdValue = Int32.MinValue;
public List<LinkModel> Linked { get; set; }
public List<LinkModel> NotLinked { get; set; }
protected MessageModel()
{
Id = DefaultIdValue;
Linked = new List<LinkModel>();
NotLinked = new List<LinkModel>();
}
protected MessageModel(string tag, string message):this()
{
Tag = tag;
Message = message;
}
}
public class TextModel:MessageModel
{
public int TextId { get; set; }
public TextModel()
{
TextId = DefaultIdValue;
}
}
This is the submission I get on the server side on submit (formatted for sanity):
Tag=
&Message=
&NotLinked.index=35fda83a053645e6809bbb8b0ea00103
&NotLinked.index=14c2e286e28b4c9d8f889fb3eb437e5f
&NotLinked.%5b35fda83a053645e6809bbb8b0ea00103%5d.RecipientId=1
&NotLinked.%5b35fda83a053645e6809bbb8b0ea00103%5d.RecipientName=Bob+Biggins
&NotLinked.%5b14c2e286e28b4c9d8f889fb3eb437e5f%5d.RecipientId=2
&NotLinked.%5b14c2e286e28b4c9d8f889fb3eb437e5f%5d.RecipientName=Billy+Oswold
&Submit=Submit
When the function is called that accepts that model the NotLinked collection is set to null. D:
The (relevant) output html looks like this (im trying to "faux" bind to:
<ol> and <li>
with jQuery doing the work of moving stuff around)
<div id="NotLinkedContainer">
<ol id="NotLinked" name="NotLinked" style="width: 500px;height: 200px">
<li value="1">Bob Biggins
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="a0ab331bee2a461084b686e13a87090b" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientId" name="NotLinked.[a0ab331bee2a461084b686e13a87090b].RecipientId" type="hidden" value="1" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientName" name="NotLinked.[a0ab331bee2a461084b686e13a87090b].RecipientName" type="hidden" value="Bob Biggins" />
</li>
<li value="2">Billy Oswold
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="d7d294d3174c4bd98d583e92010359e7" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientId" name="NotLinked.[d7d294d3174c4bd98d583e92010359e7].RecipientId" type="hidden" value="2" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientName" name="NotLinked.[d7d294d3174c4bd98d583e92010359e7].RecipientName" type="hidden" value="Billy Oswold" />
</li>
</ol>
</div>
Any ideas? Haven't done this sort of complex binding before so I'm at a loss at the simple mistake I've probably made.
Try removing the dot notation before the brackets and since this isn't a dictionary, but a list, you need to use indices, not keys. The correct syntax for a list in a razor view should look more like this:
<div id="NotLinkedContainer">
<ol id="NotLinked" name="NotLinked" style="width: 500px;height: 200px">
<li value="1">Bob Biggins
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="a0ab331bee2a461084b686e13a87090b" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientId" name="NotLinked[0].RecipientId" type="hidden" value="1" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientName" name="NotLinked[0].RecipientName" type="hidden" value="Bob Biggins" />
</li>
<li value="2">Billy Oswold
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="d7d294d3174c4bd98d583e92010359e7" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientId" name="NotLinked[1].RecipientId" type="hidden" value="2" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientName" name="NotLinked[1].RecipientName" type="hidden" value="Billy Oswold" />
</li>
</ol>
</div>
Here is an article that covers what you are attempting to do:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Resources