Default selected value for <form:radiobutton /> using spring mvc - spring

In spring mvc I am taking the dynamic hobbies values from the database.
I have to select any one the hobby.
I can take the value and rendering in HTML
Map<String, List<?>> map = new HashMap<String, List<?>>();
map.put("hobbiesList", hobbiesList);
return new ModelAndView("register", "map", map);
in html
<form:radiobuttons path="hobby"
items="${map.hobbiesList}" />
If I do that , it is showing the list, but my requirement is when loading these hobbies, the default value has to be in selected mode.

So there's two things, one is the list of available options (hobbiesList) and one is the hobby that is to be selected.
You are setting the path to hobby, but I don't see where there comes from.
You would normally pass in an Entity or Form Backing Object as the structure representing the information filled in with the form. Can you update your code to show that?
In your controller's get handler, create a form object, and set it's hobby to something:
#RequestMethod
ModelAndView getForm() {
ModelAndView mav = new ModelAndView();
MyForm myForm = new MyForm();
myForm.hobby = "some hobby";
mav.addObject("map", myForm);
//add your hobbiesList too here, or in a #ModelAttribute method
mav.setViewName("register");
return mav;
}

Related

Spring Boot Post Request Method not having all Object values

Using Spring Boot, Hibernate JPA and Thymeleaf.
I have an Order database table which currently only holds 1 record. This record has a few columns and some of the columns are not seen on any forms, they are set upon saving the Order, for instance the creation date.
On the GET request below I select the specific Order and all values are returned into the Order object as expected.
This is my GET Request method:
#RequestMapping(value = "/editorder/{orderId}", method = RequestMethod.GET)
public String editOrderGet(Model model, #PathVariable long orderId)
{
Order order = orderService.findById(orderId);
model.addAttribute("order", order);
return "/editorder";
}
This is a small snippit of my edit order html form using Thymeleaf, binding the Order object to the form using th:object as below:
<form role="form" th:action="#{/editorder}" th:object="${order}" method="post">
<input type="hidden" th:field="*{orderId}"/>
<button type="submit" class="btn btn-primary">Update Order</button>
.
.
</form>
And this is my POST Request method:
#RequestMapping(value = "/editorder", method = RequestMethod.POST)
public String editOrderPost(Model model,
#Valid #ModelAttribute("order") Order order, BindingResult bindingResult)
{
//rest of code here
}
As you can see, on the GET request I am adding the Order object to the model.
On the html form, I am binding the Order object to the entire form. Then on the POST request I am getting the Order object.
But on the POST it is seen as a new Order and only contains the fields as specified in the form, it does for instance not contain the creation date as seen in the GET request.
My question is this:
Am I missing something or do I explicitly need to go set each of those fields as hidden fields on my form?
In your GET response you may be returning the whole Order object into the Model, but Thymeleaf when trying to build the actual html from template will pick only the items it needs to build the template. So only the fields that are used in the form are used to build the form in your html page.
So when u resubmit the form to the POST service only those fields that are available in the form is reposted.
If u want these fields to be displayed on the page then add these fields in the Form. Thymeleaf picks them and displays in the form. If you dont want them to be shown in the Page then just ignore them. The Order object which u receive in the POST would not have that fields as they were not available in original form.
U can get them by querying the database, any how you do have the order id saved as the Hidden field.
public String editOrderPost(Model model,
#Valid #ModelAttribute("order") Order order, BindingResult bindingResult){
Order orderFromDB = orderService.findById(order.getId());
// Code to update the orderFromDB from order object
orderService.save(order);
}
This will save the updated fields to the database.
Generally its not a good practice to expose the Entity objects to the API. Try using a DTO/value object. This can have only fields that define your business fields. Also u can use BeanMapper frameworks like dozer/mapstruct/modelmapper to copy from DTO to Entity and vice versa.

How could i dynamically bind data in checkbox in mvc3 razor

I am working in mvc3 razor.
i want checkbox input in razor view for all catagories stored in database.
how could i bind it? please help
Suppose your model is having a field to hold all the checkbox text like.
public class MyClass
{
public string SelectedOptions {get;set;}
public List<String> CheckList {get;set;}
}
Write a controller Action method like
public ActionResult ShowCheckBoxList()
{
MyClass Options= new MyClass();
Options.CheckList = new List<String>();
// Here populate the CheckList with what ever value you have to
// either if you are getting it from database or hardcoding
return View(Options);
}
you have to create a view by right clicking the above method and choose Add View. Make sure you keep the name same as the method name also you the strongly typed view by choosing the MyClass Model from the dropDown, scaffolding template is optional use it as per your scenario.
Now in your View you can use this populated check box text as
#foreach(var optionText in Model.CheckList)
{
#Html.CheckBox(#Model.SelectedOptions, false, new {Name = "SelectedOptions", Value = #optionText})
#Html.Label(#optionText , new { style = "display:inline;" })
}
Keep this in a form and make sure you also specify a Action to be called on post of the form.
Make your action name same as the previous action (it is [GET] meaning before post), Now we create same method for [POST]
[HTTPPOST]
public ActionResult ShowCheckBoxList(MyClass data) // here you will get all the values from UI in data variable
{
//data.SelectedOptions will have all the selected values from checkbox
}

Spring MVC - difference between HttpSession.setAttribute and model.addObject

I am trying to learn Spring MVC recently. It seems that i did not understand well the functionalities of #ModelAttribute annotation and HttpSession.
#SessionAttributes({"shoppingCart", "count"})
public class ItemController {
#ModelAttribute("shoppingCart")
public List<Item> createShoppingCart() {
return new ArrayList<Item>();
}
#ModelAttribute("count")
public Integer createCount() {
return 0;
}
#RequestMapping(value="/addToCart/{itemId}", method=RequestMethod.GET)
public ModelAndView addToCart(#PathVariable("itemId") Item item,
#ModelAttribute("shoppingCart") List<Item> shoppingCart, #ModelAttribute("count") Integer count) {
if(item != null) {
shoppingCart.add(item);
count = count + 1;
}
return new ModelAndView(new RedirectView("showAllItems")).addObject("count", count);
}
#RequestMapping(value="/deleteFromCart/{itemId}", method=RequestMethod.GET)
public ModelAndView deleteFromCart(#PathVariable("itemId") Item item,
HttpSession session) {
List<Item> list = (List<Item>) session.getAttribute("shoppingCart");
list.remove(item);
//session.setAttribute("shoppingCart", list);
Integer count = (Integer) session.getAttribute("count");
count = count - 1;
session.setAttribute("count", count);
return new ModelAndView(new RedirectView("showAllItems"));
}
ShoppingCart and count are the session attributes.
The problem is in the deleteFromCart method. I get the count from session, reassign it and overwrite it in session. But i cant see the updated value of count on jsp. However, the updated shoppingCart object can be seen updated, although i do not overwrite the session object (since the object is the same object which is already in session).
But why is the count not updated, although i overwrite it with session.setAttribute?
When i add the new count object to the model (model.addObject("count", count)) then i can see the updated value of count. But why does not session.setAttribute give the same result?
First of all, #SessionAttribute does not have to use the http session. It uses a SessionAttributeStore which can have anything as its backing storage. Only the default implementation uses the http session.
The reason why your code does not work as expected lies in how #SessionAttribute works.
Before a controller method is invoked, everything listed in #SessionAttributes, in your case {"warenkorb", "count"}, is read from the session and added to the model.
After the method has returned the session is updated with everything that has been added to the model within the method.
.addObject("count", count)
-> count is added to the model and afterwards to the session.
session.setAttribute("count", count)
-> count is added to the session but not to the model. It will be added to the model before the next invocation of any controller method. But as for now the model still has the old count. And the model is what gets added to the request. And if an attribute can be found in the request scope then the jsp does not care about what's in the session.
When you use #SessionAttributesand #ModelAttribute (or Spring MVC in general) then avoid using HttpSession or HttpRequest. Even HttpResponseis of limited use. Embrace the beauty of Spring MVC instead :)
model.addObject puts object to the request scope while HTTPsession.setAttribute puts it to the session scope. And since variables on jsp are resolved on the next order: page scope -> request scope -> session scope -> application scope, you get what you get.
Java method params are passed by values. You can assign to this paramateter anything yoou want inside the method, but it won't have ny effect outside of it . Insisde of the method you're dealing with the copy of the param

Spring MVC: How to retrieve data apart from the Model submitted to a view

I have the following requirement. I submit a Model object to a view as follows...
#RequestMapping(value ="/addItem", method = RequestMethod.GET)
public ModelAndView showContacts() {
ModelAndView modelAndView = new ModelAndView("addItem", "command", new Item());
return modelAndView;
}
But on post, I need to retrieve a value apart from the "Item" object (model) that is returned to me. I can't have this variable be a part of the Item model object because it does not belong there. But I need it returned in order to act on that value. How can I get about doing this ?
I.e. In my JSP file, I have the following fields...
<form:input type="text" path="val1"/>
<form:input type="text" path="val2"/>
<form:input type="text" path="val3"/>
Out of the above, only fields val1 and val2 have mappings to the Item object, where as val3 does not. Nevertheless, I need the value of val3 passed back to my controller as well. The code I have right now to handle the POST is as follows, but I can't figure out how to get the value for val3. The code does not compile right now because it says that there is no field or appropriate getter method in the Item class for val3.
#RequestMapping(value = "/postItem", method = RequestMethod.POST)
public String postItem(#ModelAttribute("item") Item item , BindingResult result) {
logger.info("Post Item:");
return "home";
}
How can I modify the above code to suite my requirement ?
Some guidance on this matter will be highly appreciated.
You can pass a map as the model, and include all sorts of different things in there. You are not limited to a single domain object, that constructor is there as a convenience, it is not the only way to do it. There is a variation of the constructor:
public ModelAndView(Object view,
Map model)
Create a new ModelAndView given a View object and a model.
Parameters:
view - View object to render (usually a Servlet MVC View object)
model - Map of model names (Strings) to model objects (Objects).
Model entries may not be null, but the model Map may be null if
there is no model data.

How do I pass an object from the Index view to the edit view using MVC3

I have created a simple WCF service that is to be configured by an MVC3 UI.
When I call the index page from my controller, I want to display the values held in the configuration, which has been returned by the service. The user could then chose to edit these settings and then send them back to the service.
I want to do something like this in the index view ...
<div>
#Html.ActionLink("Edit", "Edit", model)
</div>
and then consume the model in the controller like this...
[HttpPost]
public ActionResult Edit( SettingsModel Config)
{
try
{
List<string> configErrors = null;
if (ModelState.IsValid)
{
// Set up a channel factory to use the webHTTPBinding
using (WebChannelFactory<IChangeService> serviceChannel = new WebChannelFactory<IChangeService>(new Uri(baseServiceUrl)))
{
IChangeService channel = serviceChannel.CreateChannel();
configErrors = channel.SetSysConfig(Config);
}
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
but this doesn't work.
Any suggestions???
When the form gets posted, all the input type fields data is collected and sent to the server. You can see this data using FireBug. The key point here is that, is the data that is being posted in a form, that MVC's default model binder can understand and map it to the model object, which is being passed as input parameter to the action method.
In your case, the model is of type "SettingsModel". You have to ensure that, the form data that is being posted is in format, that can be mapped to the "SettingsModel" object.
Same kind of question discussed in another thread : Can't figure out why model is null on postback?
Check Out this article : NerdDinner Step 6: ViewData and ViewModel
In the above article, carefully go through the "Using a ViewModel Pattern" section. My guess is that, this is what you are looking for.
You will need to post the values to populate the SettingsModel object on the Edit action. You can do this using hidden form fields if you don't want the user to see it. Otherwise you could have no parameters on the Edit action and make another call to the web service to populate the Settings model.

Resources