Spring MVC bind multi select with view model on post method - spring

How to bind a multi select to a view model on post method?
This is the view model:
public class AssignEvaluationViewModel {
private String evaluationType;
private String milestone;
private List<AssigneesViewModel> optionsList;
//getters and setters
}
public class AssigneesViewModel {
private int evaluatorId;
private int evaluatedId;
private String evaluatorName;
private String evalueatedName;
}
Controller
#RequestMapping(value="addAssignment", method = RequestMethod.GET)
public String addAssignment(Model model){
// load the list of evaluation type
List<DropDownListItem> items = new ArrayList<DropDownListItem>();
items.add(new DropDownListItem("1", "Peer evaluation"));
items.add(new DropDownListItem("2", "Team member evaluation"));
items.add(new DropDownListItem("3", "Team evaluation"));
model.addAttribute("items", items);
// load the list of milestones
List<DropDownListItem> milestones = new ArrayList<DropDownListItem>();
List<MilestoneDTO> dtos = milestoneService.getAll();
for (MilestoneDTO m : dtos) {
milestones.add(new DropDownListItem(String.valueOf(m.getId()), m
.getMilestoneName()));
}
model.addAttribute("milestones", milestones);
model.addAttribute("addAssignment", new AssignEvaluationViewModel());
return "addAssignment";
}
#RequestMapping(value="addAssignment", method = RequestMethod.POST)
public String addAssignmentPOST(#ModelAttribute("addAssignment") AssignEvaluationViewModel viewModel){
//save the assignment
return "redirect:assignEvaluationForms";
}
The problem is in the jsp.
<form:form commandName="" modelAttribute="addAssignment" id="addAssignment">
//..................
<div class="selectAssignees">
<p>Assignees:</p>
<form:select multiple="multiple" class="assigneesOptions" path="optionsList" id="assignees">
</form:select>
</div>
//..............
</form:form>
How do i bind the options added by the user in the select with optionsList from the AssignEvaluationViewModel?

If you want to show options in Spring you can use form:options
<form:form commandName="" modelAttribute="addAssignment" id="addAssignment">
<div class="selectAssignees">
<p>Assignees:</p>
<form:select multiple="multiple" class="assigneesOptions" path="optionsList" id="assignees">
<form:option value="NONE" label="--- Select ---"/>
<form:options items="${optionsList}" />
</form:select>
</div>
</form:form>

Related

Is greeting view and the result view pointing to the same object?

Here our controller may return one of two views.
In such a case where these 2 method signatures both contained Model Model Map and ModelAttribute, do the views share access to the Model and ModelAttribute loaded by a previous request handle?
#Controller
public class GreetingController {
#GetMapping("/greeting")
public String greetingForm(Model model) {
model.addAttribute("greeting", new Greeting());
return "greeting";
}
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting) {
return "result";
}
}
It does not point the same object.
I am assuming you are using https://spring.io/guides/gs/handling-form-submission/
and its code naming convention is quite confusing.
Please see the following test code.
I changed URL, variable name purposely.
Greeting.java
public class Greeting {
private long id;
private String content;
//... getters and setters
}
Greeting2.java
//created for testing
public class Greeting2 {
private long id;
private String content;
//... getters and setters
}
GreetingController.java
#Controller
public class GreetingController {
#GetMapping("/greeting") // greeting URL and GET request method
public String greetingForm(Model model) {
// th:object="${foo}" in template and thymeleaf
model.addAttribute("foo", new Greeting());
return "greeting_tmpl"; // src/main/resources/templates/greeting_tmpl.html
}
#PostMapping("/greeting_post")
public String greetingSubmit(#ModelAttribute Greeting2 bar) {
//I expected using bar variable in result_tmpl, but it used Greeting2(lowercase) as variable
return "result_tmpl"; // src/main/resources/templates/result_tmpl.html
}
}
src/main/resources/templates/greeting_tmpl.html
...
<body>
<h1>Form</h1>
<form action="#" th:action="#{/greeting_post}" th:object="${foo}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
src/main/resources/templates/result_tmpl.html
...
<body>
<h1>Result</h1>
<p th:text="'id: ' + ${greeting2.id}" /> <!-- this name should be like bar.id not greeting2 -->
<p th:text="'content: ' + ${greeting2.content}" />
Submit another message
</body>
</html>
Simply,
Browser triggers #GetMapping.
Server Parses Greeting model to HTML form values in greeting template and response to the browser.
Submit Form Data using POST method triggers #PostMapping.
#ModelAttribute Greeting2(Can be any model which can parse form values(in this case, id,content) will parse form values to Greeting2 model.
Server Parses Greeting2 model to HTML form values in greeting template and response to the browser.

How to proceed with complex object in POST request

Hello SO I had 2 entities
Main entity
#Entity
#Table(name = "Events")
public class Event {
//Some fields ...
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "event_eventtypes" ,
joinColumns = #JoinColumn(name = "event_id"),
inverseJoinColumns = #JoinColumn(name = "event_type_id"))
private Set<EventType> eventTypes;
//Getters and setters...
Now I have a form that is created using spring form-taglib
<form:form modelAttribute="event" method="post" action="/event/registerEvent" commandName="event">
<form:label path="name">Event display name</form:label>
<form:input path="name" type="text" cssClass="form-control" placeholder="Display name"/>
<form:label path="description" >Description</form:label>
<form:textarea path="description" cssClass="form-control"/>
<form:label path="priv" cssClass="">Make private? <span style="font-family:'Open Sans', sans-serif; font-size:11px; color: dodgerblue;">(It will be seen by your friends and people who you send invitation.)</span></form:label>
<form:checkbox path="priv" cssClass="form-check-input"/>
<form:label path="age">Age limit</form:label>
<form:select path="age">
<form:options items="${age}"/>
</form:select>
<form:hidden path="lng" id="formLang" />
<form:hidden path="lat" id="formLat"/>
<%--Question appear here--%>
<form:select path="eventTypes" items="${eventTypes}" multiple="true"/>
<input type="submit" value="Submit">
Controller
#Controller
public class EventController {
private static final Logger logger = LoggerFactory.getLogger(EventController.class);
#Autowired
private EventService eventService;
#Autowired
private UserService userService;
#Autowired
private EventTypeService eventTypeService;
#RequestMapping(path = "/event/create", method = RequestMethod.GET)
public String init(ModelMap modelMap) {
List<String> tags = eventTypeService.listEventTypes().stream().map(EventType::getName).collect(Collectors.toList());
ArrayList<Integer> ageArr = new ArrayList();
ageArr.add(0);
ageArr.add(6);
ageArr.add(12);
ageArr.add(16);
ageArr.add(18);
modelMap.addAttribute("event", new Event());
modelMap.addAttribute("age", ageArr);
modelMap.addAttribute("eventTypes", tags);
return "/event/create";
}
#RequestMapping(path = "/event/registerEvent", method = RequestMethod.POST)
public String createEvent(#ModelAttribute("event") Event event, #ModelAttribute("eventTypes1") List<String> eventTypes){
event.setDate(new Date());
event.setUser(userService.getUserByUsername(
AuthenticationService.getLoggedInUser())
);
eventService.addEvent(event);
return "redirect:/";
}
When complete form with values, click submit, get error
400 The request sent by the client was syntactically incorrect.
It's because eventTypes property is of String type. How can I send that list as another parameter in controller or what should I do it?
Maybe you need a DTO to include event and eventType list both.
When I have done this I send a DTO with a list of IDs/Strings for event types to the form and then create a new event from the DTO.
For the select statements loop round each option returned in the DTO and use a service findById to retrieve each eventType and then add this to the event model.
for (String tag : eventDTO.getEventTags()) {
EventType eventTag = eventTypeService.findById(Long.valueOf(tag));
if (eventTag != null) {
event.getEventTypes().add(eventTag );
}
}
Found soulution.
Just implement jsp-based form as :
<form:form modelAttribute="event" method="post" action="/event/registerEvent" commandName="event">
...
<%--There I'm not using more jsp tabs.--%>
<select multiple name="et" id="tags">
<c:forEach items="${eventTypes}" var="e">
<option value=${e}>${e}</option>
</c:forEach>
</select>
<input type="submit" value="Submit">
</form:form>
In Controller I get parameters as request.getParameterValues("et")) - that return String[] from HttpServletRequest

Populate Dropdown list from Using Spring,Hibernate

Experts,
Class EmployeeEntity
{
id
Fname
Salary
Phone
}
Controller.java
#RequestMapping(value = "/list")
public String listEmployee(ModelAndView map)
{
map.addObject("employee", employeeManager.getEmp());
return "emp";
}
EmployeeDAO.java
#Override
public List<EmployeeEntity> getEmp() {
return this.sessionFactory.getCurrentSession().createQuery("select e.id, e.firstname from EmployeeEntity e").list();
}
emp.jsp
<form:form method="POST">
<form:select path="Fname">
<form:options items="${employee}" />
</form:select>
</form:form>
This are my files. I am not geting values in drropdown.Please help me How to find out problem. I need to populate list with Fname ,and Id as value in list
Error
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
First thing you have to use map instead of list. You can have a refernce to below code:
#RequestMapping(value = "/list")
public Map listEmployee(ModelAndView map) throws Exception {
Map referenceData = new HashMap();
Map<String,String> country = new LinkedHashMap<String,String>();
country.put("US", "United Stated");
country.put("CHINA", "China");
country.put("SG", "Singapore");
country.put("MY", "Malaysia");
referenceData.put("countryList", country);
}
And iterate over Map on JSP to construct dropdown as below:
<form:select path="country">
<form:option value="NONE" label="--- Select ---"/>
<form:options items="${countryList}" />
</form:select>

#NumberFormat Annotation not working

Trying to show the currency symbol in JSP but I don't see it. Did my research and I just don`t know what more should I add to get it working. This is what I have.
<mvc:annotation-driven />
Controller
#NumberFormat(style = Style.CURRENCY)
private Double value = 50.00;
#ModelAttribute("value")
#NumberFormat(style = Style.CURRENCY)
public Double getValue() {
return value;
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView loadForm(#ModelAttribute("user") User user) {
ModelAndView instance
modelAndView.addObject("value", 100.00);
return modelAndView;
}
JSP
<spring:bind path="value">
<input type="text" name="${value}" value="${value}"/>
</spring:bind>
<spring:bind path="value">
${value}
</spring:bind>
Output
<input type="text" name="value" value="100.0"/>
100.0
Try using the string literal value for the name attribute instead of resolving it with EL
<spring:bind path="value">
<input type="text" name="value" value="${value}"/>
</spring:bind>
Also, move the field value into a new object. Currently I do not believe the code is using the field in the controller or the getter in the controller.
public class MyForm(){
#NumberFormat(style = Style.CURRENCY)
private Double value = 50.00;
#ModelAttribute("value")
#NumberFormat(style = Style.CURRENCY)
public Double getValue() {
return value;
}
}
Then add the object to the model in the controller:
#RequestMapping(method = RequestMethod.GET)
public ModelAndView loadForm(#ModelAttribute("user") User user) {
ModelAndView instance
modelAndView.addObject("myForm", new MyForm());
return modelAndView;
}
Then access via the jsp:
<spring:bind path="myForm.value">
<input type="text" name="${status.expression}" value="${status.value}"/>
</spring:bind>
<spring:bind path="myForm.value">
${status.value}
</spring:bind>
The major issue at the moment with the code is that it is not using the field/accessor, it is simply placing a value in the model, which does not use any of the annotated fields/methods.
References:
http://www.captaindebug.com/2011/08/using-spring-3-numberformat-annotation.html#.UOAO_3fghvA
How is the Spring MVC spring:bind tag working and what are the meanings of status.expression and status.value?

Spring framework bind form array property

// my form
public class myForm {
private double[] myField;
public double[] getMyField(){
return myField;
}
public void setMyField(double[] myField){
this.myField = myField;
}
}
// my jsp
...
...
<c:set var="i" value="0"/>
<c:forEach items="${myList}" var="data">
<form:input path="myField[${$i}]"/>
<c:set var="i">${i + 1}</c:set>
</c:forEach>
...
...
After spring render jsp generate this code ;
<input type="text" value="0.0" name="myField0" id="myField0"/>
<input type="text" value="0.0" name="myField1" id="myField1"/>
<input type="text" value="0.0" name="myField2" id="myField2"/>
...
...
Spring cant bind my form on controller , because form names not valid (myField0, myField1..) . If i change names with firebug (as myField[0], myField[1] etc.) initBinder works and i catch my form data on controller. How can i solve this?
Thanks.
Use a Collection in your form instead of an array :
public class myForm {
private Collection<Double> myField;
public Collection<Double> getMyField(){
return myField;
}
public void setMyField(Collection<Double> myField){
this.myField = myField;
}
}

Resources