How to check if checkbox is checked when submiting a form in Thymeleaf and Spring boot? - spring

I want to check if the checkbox is checked when submitting a form.
I need to validate the user input at server side so I am using Spring MVC Form validator.
I am checking the form with a UserFormValidator class but I do not find how to validate the field checkbox.
The html code:
<form method="post" th:action="#{/addUser}" th:object="${userForm}">
<!-- other fields ... -->
<input type="checkbox" name="isTermsChecked" value="" th:checked="${isChecked}">
<span class="text-danger" th:text="${errorTermsChecked}"></span>
<button type="submit">Get Started</button>
</form>
That's what I did in the Controller class:
#PostMapping(value = "/addUser")
public ModelAndView addUser(#Valid #ModelAttribute("userForm") UserForm userForm, BindingResult bindingResult, String isTermsChecked) {
ModelAndView modelAndView = new ModelAndView();
boolean isChecked = false;
System.out.println("isTermsChecked: "+isTermsChecked);
//check is checkbox checked
if (isTermsChecked == null) {
modelAndView.addObject("isChecked", isChecked);
modelAndView.addObject("errorTermsChecked", "Please accept the Terms of Use.");
}else{
isChecked = true;
modelAndView.addObject("isChecked", isChecked);
modelAndView.addObject("errorTermsChecked", "");
}
if (bindingResult.hasErrors() || isTermsChecked == null) {
modelAndView.setViewName("view_addUser");
} else {
//add user ...
modelAndView.setViewName("view_addUser");
}
return modelAndView;
}
My code seems to work correctly and I do not know if it's the correct way.

I only removed th:field=*{checked} and everything is working properly and that's what I did:
<input name="checked" class="form-check-input" type="checkbox" th:checked="*{checked}" />
and in the controller:
#PostMapping(value = "/contact")
public String contactUsHome(#Valid #ModelAttribute("mailForm") final MailForm mailForm, BindingResult bindingResult)
throws MessagingException {
if (bindingResult.hasErrors()) {
return HOME_VIEW;
} else {
emailService.sendSimpleMail(mailForm);
return REDIRECT_HOME_VIEW;
}
}
and for the validation I used Spring Validation:
public class MailValidator implements Validator {
//...
#Override
public void validate(Object obj, Errors errors) {
//...
MailForm mailForm = (MailForm) obj;
validateChecked(errors, mailForm);
//...
}
private void validateChecked(Errors errors, MailForm mailForm) {
if (mailForm.isChecked() == false) {
errors.rejectValue("checked", "mailForm.checked");
}
}
}

Related

Spring form binding return null with many-2-one relationship

Here is the problem, when I try to submit form, user entity returns null.
Form is
<form:form class="g-form" modelAttribute="objView" id="userAssignmentForm">
<form:hidden path="id" value="${objView.id}"/>
${objView.user.id}
<div class="g-form-group required">
<label for="user">User</label>
<form:hidden id="user" path="user" value="${objView.user}"/>
<input type="text" value="${objView.user.userName}" readonly="true"/>
<input type="button" class="import-input" onclick="gImport.showImportUserForm()"/>
</div>
Controller is
#RequestMapping(value = "/create", method = RequestMethod.POST)
public #ResponseBody
String create(
#ModelAttribute("objView") UserAssignmentView objView, BindingResult result,
SessionStatus status,
HttpServletRequest request) throws UnsupportedEncodingException {
UserAssignment obj = new UserAssignment();
obj.setUser(objView.getUser());
userAssignmentService.create(obj);
return "ok";
}
Model is below contains a view entity. What am I missing?
public class UserAssignmentView extends UserAssignment {
public UserAssignmentView() {
}
public UserAssignmentView(UserAssignment obj) {
setId(obj.getId());
setStatus(obj.getStatus());
setUser(obj.getUser());
}
}
And this is form view part of controller
#RequestMapping(value = "/form", method = RequestMethod.POST)
public ModelAndView form(HttpServletRequest request) {
UserAssignment obj = new UserAssignment();
Account account = AccountRegistry.getByHttpSession(request.getSession());
ModelAndView modelAndView = new ModelAndView("forms/userAssignmentForm");
modelAndView.addObject("objView", UserAssignmentWrapper.wrap(obj));
return modelAndView;
}
I could not solve since 3 days, how can I set user to userassignment?

How to use ValidationUtils in spring

I want to use ValidationUtils as follows. But I cannot instantiate errors object since Errors is an Interface. Can you tell me how I can make this working without using a validator?
if(visitorDetails==null)
{
Errors errors;
visitorDetails=new Visitor();
ValidationUtils.rejectIfEmpty(errors, "VisitorInfo", "Selected Visitor Details Not Found");
}
Read this : Validation...
However you must implement the Validation interface in a class, and than use it to validate your object, and to do that you autowire validator in your controller..
This is an example:
public class PersonValidator implements Validator {
/**
* This Validator validates *just* Person instances
*/
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() < 0) {
e.rejectValue("age", "negativevalue");
} else if (p.getAge() > 110) {
e.rejectValue("age", "too.darn.old");
}
}
}
and in your controller:
....
#Autowired
private PersonValidator personValidator;
#InitBinder
protected void initBinder(final HttpServletRequest request, final ServletRequestDataBinder binder) {
binder.addValidators(personValidator);
}
...
Assuming you are using Spring Boot.
If using application.properties (under project/src/resources) put the following in it:
spring.messages.basename=validation
Now put a validation.properties (under project/src/resources) and put the following (for example) in it:
NotEmpty=This field is required.
Your model (AppUser in this case) should have:
private String useremail;
getters/setters;
Create a component (Class) like this (example):
#Component
public class UserAddValidator implements Validator {
#Autowired
private UserService userService;
#Override
public boolean supports(Class<?> aClass) {
return AppUser.class.equals(aClass);
}
#Override
public void validate(Object o, Errors errors) {
AppUser user = (AppUser) o;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "useremail", "NotEmpty");
}
}
The following goes to your controller:
#RequestMapping(value = "registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("userForm") AppUser userForm, BindingResult bindingResult, Model model) {
useraddValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "userregistration";
}
userService.save(userForm);
model.addAttribute("success", "User " + userForm.getUsername() + " created successfully");
return "success";
}
Last but not the least, in your view put similar to this:
<div class="row">
<label class="col-md-3" for="useremail">Email-ID</label>
<div class="col-md-8">
<spring:bind path="useremail">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="useremail" class="form-control"
placeholder="Email-id" autofocus="true"></form:input>
<form:errors path="useremail">${emailerror}</form:errors>
</div>
</spring:bind>
</div>
</div>
The result should look (something) like below:
You can look HERE for more validations.
If I understand your question correctly you want to get the errors object.
In your case I would suggest below approach.
if(visitorDetails==null)
{
visitorDetails=new Visitor();
Errors errors = new BeanPropertyBindingResult(visitorDetails, visitorDetails.getClass().getName());
ValidationUtils.rejectIfEmpty(errors, "VisitorInfo", "Selected Visitor Details Not Found");
}
Let me know if you need more help.
you can use it to make some constraint on some of your field like show error when the field is empty or emptywithspace , this class already contain some static method that can do that
below an exemple for using ValidationUtils class
public class UserValidator implements Validator {
public boolean supports(Class clazz) {
// TODO Auto-generated method stub
return Employee.class.equals(clazz);
}
public void validate(Object target, Errors errors) {
// TODO Auto-generated method stub
ValidationUtils.rejectIfEmpty(errors, "email", "email");
ValidationUtils.rejectIfEmpty(errors, "password", "password");
Employee emplo = (Employee) target;
if(emplo.getEmail() != null && emplo.getEmail()=="aa") {
errors.rejectValue("email", "email invalide ");
}

Spring 4.0 missing validation errors

Not sure what am I doing wrong - but after I submit the person form without any value
I am unable to see any validation error in the html output.
When I add a breakpoint in the controller I am able to see the "errors"
So it is going to result.hasErrors() tried to add * form:errors path="*" - still nothing
but still errors are not on the form.
Get method:
Person class is a POJO with no annotations.
#RequestMapping(value="/person/add" , method = RequestMethod.GET)
public ModelAndView personAdd() {
ModelAndView modelAndView = new ModelAndView("personAdd");
Person person = new Person();
person.setCreationDate(new Date());
modelAndView.addObject(person);
return modelAndView;
}
post method to save the new person
#RequestMapping(value="/person/add" , method = RequestMethod.POST)
public ModelAndView processSubmit(#ModelAttribute("person") Person person,BindingResult result) {
personValidator.validate(person, result);
if (result.hasErrors()) {
ModelAndView modelAndView = new ModelAndView("personAdd");
modelAndView.addObject(person);
return modelAndView;
} else {
ModelAndView modelAndView = new ModelAndView("refreshParent");
dao.persist(person);
return modelAndView;
}
}
The personValidator:
#Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "personName","required.personName", "Name is required.");
The Person form (for simplicity only name is there)
<form:form method="POST" modelAttribute="person" action="${pageContext.request.contextPath}/person/add">
<form:errors path="*" cssClass="errorblock" element="div"/>
<form:errors path="*" />
<div class="form-group">
<label class="control-label" for="inputError">Person Name:</label>
<form:input path="personName" class="form-control" placeholder="personName"/>
<form:errors path="personName" cssClass="error" />
</div>
<form:form>
ModelAndView modelAndView = new ModelAndView("personAdd");
This line constructs a a new ModelAndView and by doing that you dismiss the current model. You add only the object in the line following this, but you have effectivly destroyed the binding results already available. If you use this construct pass in the model from the BindingResults. And you don't have to add the model object anymore as that is already included.
ModelAndView modelAndView = new ModelAndView("personAdd", result.getModel());
However with the annotation driven #Controller you don't have to return a ModelAndView in this case a simple String would suffice.
#RequestMapping(value="/person/add" , method = RequestMethod.POST)
public ModelAndView processSubmit(#ModelAttribute("person") Person person,BindingResult result) {
personValidator.validate(person, result);
if (result.hasErrors()) {
return "personAdd";
} else {
dao.persist(person);
return "refreshParent";
}
}
This will render the correct view and leave the current model (which contains the errors) intact.
You could even apply automatic validation by adding #Valid to your model attribute argument and include a #InitBinder annotated method.
#RequestMapping(value="/person/add" , method = RequestMethod.POST)
public ModelAndView processSubmit(#Valid #ModelAttribute("person") Person person,BindingResult result) {
if (result.hasErrors()) {
return "personAdd";
} else {
dao.persist(person);
return "refreshParent";
}
}
#InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.setValidator(personValidator);
}
Try to put this configuration:
#RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(#Valid #ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}
And put this in your person class
#NotNull
String personName;
And do not forget to place in your Spring XML file or the same but in your java configuration
<mvc:annotation-driven/>
All this will do the validation

Why is Spring not running my Validator?

I am using Spring MVC and I am making a Validator but it looks like Spring is never running it.
Here is my Validator is a easy one right now just checking for two fields
public class MemberRequestValidator implements Validator {
public boolean supports(Class aClass) {
return MemberRequest.class.equals(aClass);
}
public void validate(Object obj, Errors errors) {
MemberRequest mr = (MemberRequest) obj;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "content", "Content field is Required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "areacode", "Area code field is Required");
}
}
Now my controller looks like the following:
#InitBinder("memberrequest")
public void initMemberRequestBinder(WebDataBinder binder) {
binder.setValidator(new MemberRequestValidator());
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public ModelAndView saveRequest(#ModelAttribute #Valid MemberRequest mr, BindingResult result)
{
if (result.hasErrors())
{
LOGGER.debug("Pages had errors on it... returning to input page");
return new ModelAndView("question");
}
else
{
String Ticket = mService.sentWebRequest(mr);
Map<String, Object> model = new HashMap<String, Object>();
Ticket t = new Ticket();
t.setTicketDetails(Ticket);
model.put("ticket", t);
return new ModelAndView("thanks", model);
}
}
and in my JSP page I have the following:
<c:url var="saveUrl" value="/mrequest/save.html" />
<form:form modelAttribute="memberrequest" action="${saveUrl}" name="memberrequest" id="memberrequest">
so if I dont enter any data in on the form I should hit the errors but I dont?
Try with #ModelAttribute("memberrequest") in handler or modelAttribute="memberRequest" in form and #initBinder("memberRequest")

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">

Resources