Spring 3 MVC capability for JSTL jsp option group label - java

I am a newbie to Spring and I want to create "option group select" But I am unable to do this.
I want an output as following but in HTML type saying
<select name="..." value"...">
<optgroup label="Category 1">
<option ... />
<option ... />
</optgroup>
<optgroup label="Category 2">
<option ... />
<option ... />
</optgroup>
</select>
General
movies
hobbies
Games
football
basketball
Images
officePics
familyPics
PresntationPics
RingTones
pop
classical
jazz
jsp code
Edited : Correct one
<form:select multiple="single" path="servicemodule" id="servicemodule">
<form:option value="None" label="--Select--" />
<c:forEach var="service" items="${servicemodule}">
<optgroup label="${service.key}">
<form:options items="${service.value}"/>
</optgroup>
</c:forEach>
</form:select>
Controller code :
There are 4 main categories and under each of these there can be many subCategories. These can be retrieved from getServiceModuleList method. But I am not getting idea where to implement the loop to store different subcategories under their respective main category.
#Autowired
private ServiceModule servicemodule;
Edited: Correct #ModelAttribute
#ModelAttribute("servicemodule")
public Map<String,List<String>> populateService() {
String[][] mainCategory = new String[7][2];
mainCategory[0][0]= "General"; mainCategory[0][1]= "general1234";
mainCategory[1][0]= "Games"; mainCategory[1][1]= "games1234";
mainCategory[2][0]= "Images"; mainCategory[2][1]= "images1234";
mainCategory[3][0]= "Ringtones"; mainCategory[3][1]= "ringtone1234";
Map<String,List<String>> serviceModule=
new LinkedHashMap<String,List<String>>();
List<String> subCategory=new ArrayList<String>();
List<ServicesPojo> services=
servicemodule.getServiceModuleList("1",mainCategory[0][1],"0");
for(ServicesPojo serviceName: services)
{
subCategory.add(serviceName.getServiceName().trim());
}
serviceModule.put(scats[0][0],subService);
return serviceModule;
}
Edited: Got the Answer for Loop
for(int i=0;i<mainCategory.length;i=i+2){
List<String> subCategory=new ArrayList<String>();
List<ServicesPojo> services=
servicemodule.getServiceModuleList("1",mainCategory[0][i],"0");
for(ServicesPojo serviceName: services)
{
subCategory.add(serviceName.getServiceName().trim());
}
serviceModule.put(mainCategory[i][0],subCategory);
}
Model
This has the main error whether I should keep only String or List Confused!!
Edited: Now Corrected one
private List<String> servicemodule;
public List<String> getServicemodule() {
return servicemodule;
}
public void setServicemodule(List<String> servicemodule) {
this.servicemodule = servicemodule;
}
Error Description
org.springframework.beans.NotReadablePropertyException:
Invalid property 'serviceModule' of bean class
[springx.practise.model.SiteModel]: Bean property 'serviceModule'
is not readable or has an invalid getter method:
Does the return type of the getter match the parameter type of the setter?
Solved!!

Watch you case: servicemodule != serviceModule.
The <c:foreEach> loop isn't correct either: it uses itemGroup both for var and varStatus, and itemGroup is never used inside the loop. Instead, serviceModule is used, but is not defined anywhere.
And I have a hard time understanding your code, one of the reasons being that you use the same name for very different things and don't pluralize attributes of type List.
private ServiceModule servicemodule;
...
Map<String,List<String>> serviceModule
...
private List<String> servicemodule;
...
<form:select multiple="single" path="serviceModule" id="serviceModule">
...
<c:forEach var="itemGroup" items="${servicesModule}" varStatus="itemGroup">
No wonder you lost yourself.

Related

How to pass Object to ModelAttribute in controller - Spring

Is it possible to pass an object (car) to my controller by using a select tag? When i try to use the following code, the car parameter is not recognised and it results is:
400-Bad Request
A car consists of 2 Strings (Brand, Model)
A spot consists of 1 car and 2 Strings (town, streetName)
My jsp page:
<form:form method="post" modelAttribute="spot" action="${post_url}">
<form:select path="car">
<form:option value="-" label="--Select car"/>
<form:options items="${cars}"/>
</form:select>
<form:input type="text" path="town"/>
<form:input type="text" path="streetName"/>
<button>Save</button>
</form:form>
My controller:
#RequestMapping(value="/addSpot", method = RequestMethod.POST)
public String save(#ModelAttribute("spot") Spot spot){
service.addSpotToService(spot);
return "redirect:/spots.htm";
}
you can creta a component to convert the Long id of Car to object car
#Component
public class CarEditor extends PropertyEditorSupport {
private #Autowired CarService carService;
// Converts a Long to a Car
#Override
public void setAsText(Long id) {
Car c = this.carService.findById(id);
this.setValue(c);
}
}
in your controller add this
private #Autowired CarEditor carEditor;
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Car.class, this.carEditor);
}
and then pass the id of car in the select
<form:select path="car">
<form:option value="-" label="--Select car"/>
<form:options items="${cars}" itemValue="id" itemLabel="model"/>
</form:select>
have a look at the spring documentation http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/view.html and specifically at the section The options tag
The items attribute is typically populated with a collection or array
of item objects. itemValue and itemLabel simply refer to bean
properties of those item objects, if specified; otherwise, the item
objects themselves will be stringified. Alternatively, you may specify
a Map of items, in which case the map keys are interpreted as option
values and the map values correspond to option labels. If itemValue
and/or itemLabel happen to be specified as well, the item value
property will apply to the map key and the item label property will
apply to the map value.
Let me know if this worked for you

Spring MVC / JSP - How to pass nested list of object to controller from a select form

I am using Spring MVC with JSP.
I have a User entity which contains a list of Group entities. The relationship is Many-to-Many (a Group entity contains a list of User entities).
In my user controller I have a method for returning the add user page with an empty User entity and a list of available Group entities.
#RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView loadUserAdd() {
ModelAndView mv = new ModelAndView("user/userAdd");
mv.addObject("user", new User());
try {
mv.addObject("groups", gr.listGroups());
} catch (TestException e) {
mv.addObject("error", e.getMessage());
e.printStackTrace();
}
return mv;
}
On the userAdd page, I want to select the group(s) the user will have from the list of the available groups.
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
<select id="availableGroups" class="form-control" multiple onclick="shuttle('availableGroups', 'selectedGroups')">
<c:forEach items="${groups}" var="group">
<option value="${group.id}">${group.id}: ${group.name}</option>
</c:forEach>
</select>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
<select id="selectedGroups" class="form-control" multiple onclick="shuttle('selectedGroups', 'availableGroups')">
<c:forEach var="group" items="${user.groups}" varStatus="status">
<option value="${group.id}">${group.id}: ${group.name}</option>
</c:forEach>
</select>
</div>
</div>
Note, the 'shuttle' function moves a group from one select element to the other. E.g. from the available groups to the selected groups or vice versa. This works.
On submit, I want to have the selected groups set in the user entity so that it will arrive in the addUser method.
#RequestMapping(value = "/add", method = RequestMethod.POST)
public ModelAndView addUser(#ModelAttribute("user") User user) {
Instead on submit, the user entity contains a null list of groups. I'm sure my JSP is wrong so it would be great if someone could point me in the right direction. Any advice on improvements would be good as I'm doing this as a learning exercise. Thanks.
A college suggested a way to solve this question. The solution offered uses a single select field rather than two select fields with a shuttle moving values from available to selected and vice versa.
In the JSP, I've replaced both select fields with just one:
<div class="row">
<div class="col-xs-3 col-sm-3 col-md-3 col-lg-3">
Groups
</div>
<div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
<form:select
path="groups"
items="${availableGroups}"
multiple="true"
itemValue="id"
itemLabel="name"
class="form-control" />
</div>
</div>
This form:select iterates over the available groups and creates a option element for each. The select attributes are:
path - uses the value 'groups' to map to the getGroups getter method on the user entity in the view model (modelAndView.addObject("users", users);).
items - is the list of all available groups in the system. This is set in the model from the controller. See note about this below.
itemValue - is the value which will become the select's option's value. The 'id' maps to the getId getter method of the current group.
itemLabel - is the value which will become the select's option's visible label. The 'name' maps to the getName getter method of the current group.
The form:select also marks options as selected if the user has them set.
Here is an example output where the groups are 1,2,3,4 (both in id and name) and the user has group 1,2.
<div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
<select id="groups" name="groups" class="form-control" multiple="multiple">
<option value="1" selected="selected">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="5">4</option>
</select>
<input type="hidden" name="_groups" value="1"/>
</div>
To make 'availableGroups' available I've used:
#ModelAttribute("availableGroups")
public List<Group> initializeGroups() {
return us.listGroups();
}
This makes the list of available-groups available to each view of the controller.
On submit, to update the user with the selected groups (either adding or removing groups as this works on edit too), I've used a Converter (org.springframework.core.convert.converter.Converter).
#Component
public class GroupConverter implements Converter<String, Group> {
#Autowired
GroupService groupService;
public User convert(String element) {
User user = null;
if(element != null) {
int id = Integer.parseInt(element);
user = userService.fetchUser(id);
}
return user;
}
}
The Converter takes the id of the group and gets it from the data source then magically sets it in the user entity before the controller is called.
Converters are set on the WebMvcConfigurationSupport...
#Autowired
GroupConverter groupConverter;
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(groupConverter);
}

Infuriating empty list in Spring form / controller

I'm trying to create a list of objects from form inputs. The objects are the same but their values may differ, it's essentially a menu.
I'm still getting to grips with Spring/Thymeleaf which is adding some level of complexity to what feels like a simple task.
I've a class for the menu, a simple POJO, there is then a list of these defined as a data member in the bean itself:
private ArrayList<GuestMenuOptions> guestMenus;
I've read many posts, tried many things and am on the verge of softly resting my head against the table.
I've had several errors, most of which either tell me that the list cannot be found or that the list is empty - it's currently in stable condition where the list, no matter what I try, will not be populated, even when I load in default values...unfortunately my debugger has died which is not helping.
Any help is appreciated. thank you
EntryController:
#RequestMapping(method=RequestMethod.GET, value="/")
public String indexPage(Model model) {
model.addAttribute("childMenuOptions", generateChildMenus());
//not sure if this is neccesary...
ArrayList<GuestMenuOptions>guestMenus = new ArrayList<>();
GuestMenuOptions ad1 = new GuestMenuOptions();
GuestMenuOptions ad2 = new GuestMenuOptions();
guestMenus.add(ad1);
guestMenus.add(ad2);
GuestContactBean ctb = new GuestContactBean();
ctb.setGuestMenus(guestMenus);
model.addAttribute("guestContactBean", ctb);
model.addAttribute("formBackingBean", new FormBackingBean());
return "index";
}
Form:
<form modelAttribute="guestBean" class="contact_form" name="rsvp" role="form" th:object="${formBackingBean}" th:action="#{/sendRsvp}" method="post">
<div class="row">
<div class="form-group">
<select name="ad1Starter" id="starterMealAdult1">
<option value="!!!">-Starter-</option>
<option th:field="${guestContactBean.guestMenus[0].starter}" th:each="entry : ${adultMenuOptions.get('starter').entrySet()}" th:value="${entry.key}" th:text="${entry.value}">
</option>
</select>
</div>
<input type="submit"guest name="submit" class="btn default-btn btn-block" value="Send RSVP">
RequestController:
#RequestMapping(value = "/sendRsvp", method = RequestMethod.POST)
public String sendRsvp(#ModelAttribute("guestContactBean") GuestContactBean guestContactBean,
#ModelAttribute("guestMenus") ArrayList<GuestMenuOptions>menus,
BindingResult result) throws MessagingException {
smtpMailSender.send(guestContactBean);
return "thanksMessage";
}
Beans:
FormBacking is POJO with no reference to the menus at all.
GuestMenuOptions is the same with just starter, desert members
guestContactbean has not much more going on, basic fields with the addition of the list of GuestMenuOptions
private String numberOfAdults;
private String eventAttending;
private ArrayList<GuestMenuOptions> guestMenus;
public ArrayList<GuestMenuOptions> getGuestMenus() {
return guestMenus;
}
EDIT:
The field that populates the drop downs in working fine, it's declared as private Map<String, Map<String, String>> adultMenuOptions;
private Map<String, Map<String, String>> childMenuOptions;
they are then built in the controller so that each may have several options under 'starter', 'main' and desert' for example:
starter.put("salmon", "Smoked Salmon");
starter.put("pate", "Chicken Liver Pate");
this is then populating both the value and text of the dropdown.
If I could save the state of this Map and pass it back to the controller instead, that would also be fine but I wasn't able to why then spawned the creation of the there wrapper list.
Please revisit http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dropdownlist-selectors. It should be as simple as
class Animal {
int id;
String name;
}
then in your template:
<select th:field="*{animalId}">
<option th:each="animal : ${animals}"
th:value="${animal.id}"
th:text="${animal.name}">Wireframe</option>
</select>
I think your code is all over the place and you're mixing up menu selection with menu item types.

How to populate a drop down using string array list

Struts 1.x :
How to populate a dropdown using string array list?
In the form bean (formbean) there are getter and setter methods for the list "blockIds" which is an string arraylist. For an example
ArrayList<String> blockIds = new ArrayList<String>();
blockIds.add("A");
blockIds.add("B");
What would be the jsp code which should look like the following after rendering.
<select name=“selectedItem”>
<option value=“A”>A</option>
<option value=“B”>B</option>
</select>
See like this,
public class TestAction extends Action {
public ActionForward populateDropdown(ActionMapping mapping,ActionForm form,
HttpServletRequest request,HttpServletResponse response)
throws Exception {
ArrayList<String> blockIds = new ArrayList<String>();
blockIds.add("A");
blockIds.add("B");
MyForm myForm=(MyForm)form;
myForm.setListMsg(blockIds);
return mapping.findForward("success");
}
}
And in HTML,
<html:select property="selectedItem" styleId="standard">
<html:optionsCollection name="myForm"
property="yourList" label="label" value="value" />
</html:select>
Even you can use <logic:iterate> tags for iterate.
Hope this helps

Populate List<String> in struts2 from form data

I feel this should be exceedingly obvious, but so far I've failed to find an answer.
I want to have a list of strings (or an array of strings, I really don't care) get populated by form data in Struts2.
I've seen several examples of how to do indexed properties with beans, but wrapping a single string inside an object seems fairly silly.
So I have something like
public class Controller extends ActionSupport {
private List<String> strings = new ArrayList<String>();
public Controller() {
strings.add("1");
strings.add("2");
strings.add("3");
strings.add("4");
strings.add("5");
}
public String execute() throws Exception {
return ActionSupport.SUCCESS;
}
public List<String> getStrings() {
return strings;
}
public void setStrings(List<String> s) {
strings = s;
}
}
...
<s:iterator value="strings" status="stringStatus">
<s:textfield name="strings[%{#stringStatus.index}]" style="width: 5em" />
</s:iterator>
The form fields get populated with their initial values (e.g. 1, 2, etc), but the results are not properly posted back. setStrings is never called, but the values get set to empty strings.
Anybody have any idea what's going on? Thanks in advance!
I believe as you have it, your jsp code would render something like:
<input type="text" name="strings[0]" style="width: 5em" value="1"/>
<input type="text" name="strings[1]" style="width: 5em" value="2"/>
<input type="text" name="strings[2]" style="width: 5em" value="3"/>
...
Notice that the name of the field references are "strings[x]" where as you need the name to be just "strings". I would suggest something like:
<s:iterator value="strings" status="stringStatus">
<s:textfield name="strings" value="%{[0].toString()}" style="width: 5em" />
</s:iterator>
Not sure if the value attribute above may is correct, but I think something like this will get you the desired result.

Categories