How to bind Spring form:checkbox instead of form:checkboxes? - spring

I am having problems with form:checkbox. I cannot make it display selected values. When I selected values and submit, correct values are display in database. When I load page all values (checkboxes) are not selected.
Elements below are located inside this:
<form:form role="form" commandName="user" class="form-horizontal" action="${form_url}">
</form:form>
This works just fine:
<form:checkboxes items="${availableRoles}" path="roles" itemLabel="role" itemValue="id" element="div class='checkbox'"/>
This doesn't work:
<c:forEach items="${availableRoles}" var="r" varStatus="status">
<div class="checkbox">
<form:checkbox path="roles" label="${r.description}" value="${r.id}"/>
</div>
</c:forEach>
This is my domain class:
public class User {
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
This is my custom property editor:
public class RolePropertyEditor extends PropertyEditorSupport {
#Override
public void setAsText(String text) {
Role role = new Role();
role.setId(Integer.valueOf(text));
setValue(role);
}
}
Controller has this method:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Role.class, new RolePropertyEditor());
}
Controller method:
#RequestMapping(value = "/update/{userId}", method = RequestMethod.GET)
public String updateUser(#PathVariable Integer userId, Model model) {
User user = userService.getByUserId(userId);
List<Role> availableRoles = roleService.getAllRoles();
model.addAttribute("availableRoles", availableRoles);
model.addAttribute("user", user);
return "user/update";
}

After debugging session I found the solution.
Because of Spring internals JSP should look like this:
<c:forEach items="${availableRoles}" var="r">
<div class="checkbox">
<form:checkbox path="roles" label="${r.description}" value="${r}" />
</div>
</c:forEach>
Notice that value is item (r), not item's member like r.id.
Also you need getAsText implementation in your custom PropertyEditor.
#Override
public String getAsText() {
Role role = (Role) this.getValue();
return role.getId().toString();
}

Related

DropDownlist how to load the data using Spring boot Mysql

i am beginner of spring boot and mysql. i need to load DropDownList. i don't know how to load them.what tried so far i attached below.i want load the student name on the dropdown.
index.html- DropDown load
<select class="form-control" name="example" id="example">
<option value="0">ALL</option>
<option th:each="Student : ${allStudents}"
th:value="${Student.id}"
th:selected="${Student.isSelected(lastselected)}"
th:text="${Student.studentname}">
</option>
</select>
Student Class
package com.example.StudentCrud.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Student {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String studentname;
private String course;
private int fee;
public Student() {
}
public Student(Long id, String studentname, String course, int fee) {
this.id = id;
this.studentname = studentname;
this.course = course;
this.fee = fee;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStudentname() {
return studentname;
}
public void setStudentname(String studentname) {
this.studentname = studentname;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public int getFee() {
return fee;
}
public void setFee(int fee) {
this.fee = fee;
}
}
Contorller i wrote like this. i stuck with this area how to get the Student names only
#ModelAttribute("allStudent")
public List<Student> allUsers() {
List<Student> userList= service.listAll();
return userList;
}
Here, I'm using <form:select /> , <form:option /> and <form:options /> tags to render HTML dropdown box. And <c:forEach /> for loop each student.
Don't forget to import below taglib to jsp.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
For example, POST request path is /students. And modelAttribute="studentForm" will be used to bind Student POJO.
Index.jsp
<form:form modelAttribute="studentForm"
action="${pageContext.request.contextPath}/students" method="POST">
<form:select path="studentName">
<form:option value="NONE" label="Select" />
<c:forEach var="student" items="${allStudents}">
<form:option value="${student.id}" label="${student.studentName}"/>
</c:forEach>
</form:select>
</form:form>
By the way, I used camelCase for studentName.
Supposed service.listAll() works fine. When GET request /students is called -
Controller be like
#ModelAttribute(name = "studentForm")
public Student setUp() {
return new Student();
}
#GetMapping
public String list(Model model) {
List<Student> students = service.listAll();
// add to model
model.addAttribute("allStudent", students);
// view
return "index";
}
Method level #ModelAttribute will be invoked before any other method in controller. To use studentForm model attribute in form, we need to initialize first. You can do it without using method level #ModelAttribute.

Spring receive data from the client

Good evening!
public class Order {
private int idOrder;
private Basket basket;
// getter and setter
}
public class AnonymousOrder {
private String name;
private String telephone;
// getter and setter
}
public class UserOrder {
private User user;
// getter and setter
}
public class OrdersForm {
private List< ? extends Order> orders;
// getter and setter
}
#RequestMapping(value="/showOrders")
public String showOrders(Model model){
List<? extends Order> orders= adminManager.searchAllOrders();
OrdersShowForm ordersForm = new OrdersShowForm();
ordersForm.setOrders(orders);
model.addAttribute("ordersForm", ordersForm);
return "showOrders";
}
#RequestMapping(value="/showOrders", method = RequestMethod.POST)
public String showOrdersPOST(#ModelAttribute("ordersForm") OrdersShowForm ordersForm){
System.out.print(ordersForm);
return "showOrders";
}
<form:form modelAttribute="ordersForm">
<table class="features-table" border="1">
<c:forEach items="${ordersForm.orders}" var="order" varStatus="status">
<tr>
<c:if test="${order['class'].simpleName != 'UserOrder'}">
<td>
<input name="orders[${status.index}].name" value="${order.name}"/>
</td>
</c:if>
</c:forEach>
</table>
Problem: I am passing on page two types of data: UserOrder and AnonymousOrder, but when I try to get them on the server then come data type Order.
Question: How to transfer data to the server without changing their actual type?
P.S. sorry for my English)

Neither BindingResult nor plain target object for bean name 'loginuser' available as request attribute

#Controller
#RequestMapping("Page/Login.do")
public class HomeController
{
#RequestMapping(method = RequestMethod.GET)
protected String showLoginPage(HttpServletRequest req,BindingResult result) throws Exception
{
loginuser lu=new loginuser();
lu.setLoginn("Amit");
System.out.println(lu.getLoginn());
return "Login";
}
}
Above code is ##HomeController.java##
loginuser.java
package Com.Site.Name.Order;
public class loginuser
{
private String Loginn;
public String getLoginn()
{
System.out.println("hi i m in login get");
return Loginn;
}
public void setLoginn(String loginn)
{
System.out.println("I m in Loin set");
Loginn = loginn;
}
}
My JSP PAGE IS
Login.jsp
<form:form action="Login.do" method="post" commandName="loginuser">
<div id="Getin">
<img alt="" src="Image/loginttt.png">
</div>
<div id="login">
</div>
<form:input path="Loginn"/>
<input type="submit" value="LOGIN"/>
</form:form>
You are trying to use a Model attribute (commandName) but there is no such attribute added to the model or request attributes. You need to add it. Also, the BindingResult in your handler makes no sense. Remove it.
#RequestMapping(method = RequestMethod.GET)
protected String showLoginPage(HttpServletRequest req, Model model) throws Exception
{
loginuser lu=new loginuser();
lu.setLoginn("Amit");
System.out.println(lu.getLoginn());
model.addAttribute("loginuser", lu);
return "Login";
}
The Model attributes are added to the request attributes and are therefore available in the jsp.

Spring MVC Form Validation - The request sent by the client was syntactically incorrect

I am trying to add form validations to a working application. I started by adding a NotNull check to Login Form. I am using Hibernate impl of Bean Validation api.
Here's the code I have written
#Controller
#RequestMapping(value="/login")
#Scope("request")
public class LoginController {
#Autowired
private CommonService commonService;
#Autowired
private SiteUser siteUser;
#InitBinder
private void dateBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
binder.registerCustomEditor(Date.class, editor);
}
#ModelAttribute
protected ModelMap setupForm(ModelMap modelMap) {
modelMap.addAttribute("siteUser", siteUser);
return modelMap;
}
#RequestMapping(value="/form", method = RequestMethod.GET)
public ModelAndView form(ModelMap map){
if (siteUser.getId() == null){
map.addAttribute("command",new SiteUser());
return new ModelAndView("login-form",map);
}else {
return new ModelAndView("redirect:/my-dashboard/"+siteUser.getId());
}
}
#RequestMapping(value="/submit", method=RequestMethod.POST)
public ModelAndView submit(#Valid SiteUser user, ModelMap map, BindingResult result){
if (result.hasErrors()) {
map.addAttribute("command", user);
System.out.println("Login Error block");
return new ModelAndView("login/form",map);
}
else {
User loggedInUser = commonService.login(user.getEmail(), user.getPassword());
if (loggedInUser != null) {
siteUser.setId(loggedInUser.getId());
siteUser.setName(loggedInUser.getName());
System.out.println("site user attr set");
}
return new ModelAndView("redirect:/my-dashboard/"+loggedInUser.getId());
}
}
}
The Model is
#Component
#Scope("session")
public class SiteUser {
private Integer id = null;
#NotNull
private String name = null;
private String email = null;
private String password = null;
private List<String> displayPrivList = null;
private List<String> functionPrivList = null;
// And the getters and setters
}
The JSP is
<c:url var="loginSubmitUrl" value="/login/submit"/>
<form:form method="POST" action="${loginSubmitUrl}">
<form:errors path="*" />
<div class="row">
<div class="span4">
</div>
<div class="span4">
<h3>Please Login</h3>
<label><span style="color:red">*</span>Email</Label><form:input path="email" type="text" class="input-medium" />
<label><span style="color:red">*</span>Password</Label><form:input path="password" type="password" class="input-medium" />
<br/>
<button type="submit" class="btn btn-primary">Login</button>
<button type="button" class="btn">Cancel</button>
</div>
</div>
</form:form>
I have added messages.properties and the annotation driven bean def in the context xml.
Other answers on the subject talk about form fields not getting posted. In my case, that's the expected behavior - that if I submit a blank form, I should get an error.
Please advise what am I missing?
I think this question had the same issue as yours
Syntactically incorrect request sent upon submitting form with invalid data in Spring MVC (which uses hibernate Validator)
which just points out
You have to modify the order of your arguments. Put the BindingResult result parameter always directly after the parameter with the #Value annotation
You need this: <form:errors path="email" cssClass="errors" />
Use the tag form:errors for each input with the same "path" name.
It is also possible to list all the error at the same time if you don't put a path.
Here, check an full example with sample code that you can download to learn how to do:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/
Can you try changing the <form:form> by including the commandName to it like this
<form:form method="POST" action="${loginSubmitUrl}" commandName="user">

Spring 3 #ModelAttribute with List in model

I have two models :
public class Size {
private String name;
// getter and setter
}
public class Product {
private int id;
private String designation;
private Float price;
private List<Size> availableSizes;
// Getter and setters
}
I have defined Sizes in my servlet, and now I nead to create products with the availables sizes.
What I do in my index Controller:
ModelAndView render = new ModelAndView("admin/index");
render.addObject("products", productFactory.getProducts());
render.addObject("sizes", sizeFactory.getSizes());
render.addObject("command", p);
return render;
I've a list of products, and my list of sizes.
In my index view, I do:
<form:form method="post" action="/ecommerce/admin/products" class="form-horizontal">
<form:input path="id" />
<form:input path="designation" />
<form:input path="price" />
<form:select path="availableSizes" items="${sizes}"/>
<input type="submit" value="Ajouter le produit" class="btn" />
</form:form>
Then, in new product controller, I do :
// To fix: Sizes not saved !
#RequestMapping(value = "/products", method = RequestMethod.POST)
public ModelAndView newProduct(#ModelAttribute("Product") Product product,
BindingResult result) {
productFactory.add(product);
return buildIndexRender(null, null, product);
}
The problem is that I keet the posted product, but not the corresponding sizes.
Is there a way to keep selected sizes in the form int the controler, or directly in the model?
Thanks.
It's a very common problem.
To set a List<Size> in Product instance from the post data, that is a string colon separated list with selected sizes, all you need to do is tell the framework how to convert a size String to a Size instance. The most common approach is registering a PropertyEditor on WebDataBinder
class SizePropertyEditor extends PropertyEditorSupport {
#Override
public void setAsText(String text) throws IllegalArgumentException {
Size size = stringToSize(text); // write this code
setValue(size);
}
}
and register the property editor in Controller using #InitBinder annotation
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Size.class, new SizePropertyEditor());
}
For a more generic approach see ConversionService.

Resources