How to get checked boxes in a Controller - java

I have got a html page (with Thymeleaf):
<form action="#" th:action="#{/changeme}">
<fieldset>
<table style="width: 500px">
<tr th:each="esfield : ${esfields}">
<td>
<div>
<div class="checkbox">
<input type="checkbox" name="optionsMulti"
th:text="${esfield}" />
</div>
</div>
</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>
<button type="submit"
class="btn btn-xs btn-primary margin10-right paddingNew"
name="save">Calculate!</button>
</td>
<td></td>
</tr>
</table>
</fieldset>
</form>
When I click Calculate! it goes to my controller
#RequestMapping(value = "/changeme", params = { "save" })
public String save(final ModelMap m) {
m.addAttribute("centers", /*params*/);
return "clustering";
}
I would like to get information about checked boxes in my controller?
How can I do that?
Thank you in advance

You have basically two options :
either you use a different name for each checkbox
or you use spring tag <form:checkbox> instead of native <checkbox>
If you don't posted data will not allow you to know exactly what boxes were actually checked (excepted in cases all and none)
With the approach, you should use in your controller a #ModelAttribute annotated object containing a List<Boolean> and spring will automagically populate it with the values of your checkboxes.
#RequestMapping(value = "/changeme", params = { "save" })
public String save(#ModelAttribute BoxesForm form, final ModelMap m) {
// do what you need with form.getCheckboxes() ...
m.addAttribute("centers", /*params*/);
return "clustering";
}
public class BoxesForm {
List<Boolean> checkboxes;
// getter and setter omitted ...
}

Related

How to pass data to from view to controller in Spring-MVC?

I have a list of objects as JSON which is inside a workLists. I created a table by iterating using each on workLists and create a table in thymeleaf?
Now how can I pass work that is a single object back to the controller, what I tried is using th:object
I thought it would work but on the controller end null values are coming.
Thymeleaf section
<tr th:each="work , status : ${workLists}">
<td scope="row" th:text="${status.count}"></td>
<td>
<form th:action="#{/edit/work}" th:object="${work}" method="post">
<button type="submit" class="dropdown-item">Edit</button>
</form>
</td>
</tr>
Controller Section
#PostMapping("/edit/work")
public String editWork(#ModelAttribute("work") GetWorkkDto getWorkDto){
logger.debug(" Inside of edit work method");
return "listOfwork";
}
You need to give the contoller 2 attribues which are the workLists and a work. It will be something like:
#GetMapping("/edit/work")
public String editWork(Model model){
model.addAttribute("workLists", workLists);
model.addAttribute("workDTO", new Work());
return "listOfwork";
}
Then in your HTML page through hidden fields you give the values of the work selected:
<table>
<tr th:each="work, stat : ${workLists}">
<td>
<form action="#" th:action="#{/edit/work}" th:object="${workDTO}" method="post">
<input type="hidden" th:attr="name='id'" th:value="${work.id}" />
<input type="hidden" th:attr="name='name'" th:value="${work.name}" />
<input type="hidden" th:attr="name='description'" th:value="${work.description}" />
<p th:text="'Id : '+${work.id}"></p>
<p th:text="'Name : '+${work.name}"></p>
<p th:text="'Description : '+${work.description}"></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</td>
</tr>
</table>
You can see in the proposed code that I give the value of work.id to the workDTO.id through the name attribute (don't ask me why it is like this)
Finaly you retrieve the object in your controller (as you do already) with something like this:
#PostMapping("/edit/work")
public String editWork(#ModelAttribute Work workDTO, Model model){
System.out.println(workDTO.toString());
model.addAttribute("workLists", workLists);
model.addAttribute("workDTO", new Work());
return "listOfwork";
}

why is my form not passing information in spring boot

Hello i am passing information in a form and everything runs fine but when i fill out the form it doesnt not pass the information and i am getting this error.
There was an unexpected error (type=Internal Server Error, status=500).
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'movie_id' cannot be null
the code i am using is as folow:
#PostMapping("/save")
public String save(Movie movie) {
savedMovie.save(movie);
return "redirect:/LatestMovies";
}
And
<form th:action="#{/save}" method="post" >
<p><input type="text" id="movie_id" name="movie_id" value="" /></p>
<p><input type="text" id="movie_name" name="movie_name" value="" /></p>
<p><input type="submit" value="save" /></p>
</form>
i belive all other code is correct becuase if i try to render the db information i have no problem.
Update
This is the complete html code.
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form th:action="#{/save}" method="post" th:object="${newMovie}">
<p><input type="text" id="movie_id" th:field="*{movie_Id}"/></p>
<p><input type="text" id="movie_name" th:field="*{movie_Name}"/></p>
<p><input type="submit" value="save" /></p>
</form>
</td>
</tr>
</table>
Your controller is expecting a Movie object, but it is receiving something else, which then produces a null Movie object. You need to use th:object in your form in order to correctly send the respective class. First, let's add a new #ModelAttribute to your controller, so that your form can automatically map your Movie object in your form.
Controller
// In order to use th:object in a form, we must be able to map a new entity to that form.
// In this case we return a Movie entity.
#ModelAttribute(value = "newMovie")
public Movie newMovie() {return new Movie();}
Now, let's change your form, so that it actually sends a Movie object.
<form th:action="#{/save}" method="post" th:object="${newMovie}">
<p><input type="text" id="movie_id" th:field="*{movie_id}"/></p>
<p><input type="text" id="movie_name" th:field="*{movie_name}"/></p>
<p><input type="submit" value="save" /></p>
</form>
Note that I also changed the name attribute in your inputs, for th:field. Have in mind that in order for this to work, the name of each field must match exactly the names in your objects.
Update
In case you want to set a default value to your form, without using js and since you can't combine th:field with th:value, you could set the object's attribute in your controller.
#ModelAttribute(value = "newMovie")
public Movie newMovie() {
Movie movie = new Movie();
movie.setName("Test");
return movie;
}
Update 2
If what you want is to put the current iteration of a Thymeleaf list in your form, you can do the following.
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form th:action="#{/save}" th:object="${LatestMovies}" method="post">
<p><input type="hidden" th:value="*{id}"/></p>
<p><input type="hidden" th:value="*{movieName}"/></p>
<p><input type="submit" value="Submit"/></p>
</form>
</td>
</tr>
</table>
You forgot to mark method param with #RequestBody annotation.
This happens because the movie object you are trying to send from the form to the controller is not mapped properly. This has as a result the constraint of the movie_id you have in your movies table (PK not null I guess) to be violated by trying to insert a not null value into it. If you want the object formed in the frontend page form to be binded in a java object you could try this
front page form
<form:form action="save" modelAttribute="movie" method="POST">
<form:label path = "movie_id"> Movie id</form:label>
<form:input path="movie_id" name="movie_id">
<form:label path = "movie_name"> Movie name</form:label>
<form:input path="movie_name" name="movie_name">
<button type="submit">save</button>
</form:form>
(you should import on your page the springframework form taglib
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>)
Save controller code
#PostMapping("/save")
public String save(#ModelAttribute("movie") Movie movie) {
savedMovie.save(movie);
return "redirect:/LatestMovies";
}
Of course I am assuming that your object has a similar structure like shown below
Movie class
public class Movie{
private String movie_id; // or int or long
private String movie_name;
//getters setters constructors ommitted
}

How to have add and remove buttons in html form handle by spring 5 controller?

I am using Spring 5 and Hibernate 5.
I have got form like below in jsp file:
<form:form action="addUser" method="post" modelAttribute="user">
<table>
<tr>
<td>Name</td>
<td>
<form:input path="name" /> <br />
<form:errors path="name" cssClass="error" />
</td>
</tr>
<tr>
<td>Email</td>
<td>
<form:input path="email" /> <br />
<form:errors path="email" cssClass="error" />
</td>
</tr>
<tr>
<td colspan="1"><button type="submit">Submit</button></td>
<td colspan="1"><button type="???delete???">Remove</button></td>
</tr>
</table>
</form:form>
And UserController.java like below:
#Controller
public class UserController {
#Autowired
private UserService userService;
#GetMapping("/")
public String userForm(Locale locale, Model model) {
model.addAttribute("users", userService.list());
return "editUsers";
}
#ModelAttribute("user")
public User formBackingObject() {
return new User();
}
#PostMapping("/addUser")
public String saveUser(#ModelAttribute("user") #Valid User user, BindingResult result, Model model) {
if (result.hasErrors()) {
model.addAttribute("users", userService.list());
return "editUsers";
}
userService.save(user);
return "redirect:/";
}
}
Right now I have got a submit button which allow me to save name and email of the user.
I would like to add button REMOVE which would also relay on the same form but will instead of adding new user will be removing existing user.
Could you tell how can I do it?
Maybe the first option is to add some attribute like action, but then I need to handle it in controller and I don't know how?
Thank you.
It can be done by changing the form action dynamically based on the button click using some javascript.
<script>
$('#addBtn').click(function(){
$("#userForm").submit();
});
$('#removeBtn').click(function(){
$('#userForm').attr('action', '<your remove action>');
$("#userForm").submit();
});
<script>
<form:form action="addUser" method="post" modelAttribute="user" id="userForm">
...
<td colspan="1"><button type="button" id='addBtn'>Submit</button></td>
<td colspan="1"><button type="button" id='removeBtn'>Remove</button></td>
...
</form:form>

How to submit table data in Spring Thymeleaf

I am following given link to submit table data to be saved in database
http://viralpatel.net/blogs/spring-mvc-multi-row-submit-java-list/
But the difference between given link and my implementation is that the front-end of link uses JSTL (JSP) while i am using Thymeleaf (HTML)
Below are the files being used
HTML Form :
<form method="POST" th:action="#{/updateAllRules}" th:field="${ruleForm}">
<table>
<thead>
<tr>
<th>S No</th>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr th:each="ruleModel,iteration : ${allRules}">
<td th:text="${ruleModel.id}"></td>
<td><input type="text" th:name="${'rule'+iteration.index+'.title'}" th:value="${ruleModel.title}"></td>
<td><input type="text" th:name="${'rule'+iteration.index+'.body'}" th:value="${ruleModel.body}"></td>
</tr>
</tbody>
</table>
<br>
<input type="submit" value="Update All">
</form>
Model Class :
public class Rule {
private Integer id;
private Date timestamp;
private String title;
private String body;
// constructor and Getter/Setters
}
Form Class :
public class RuleForm {
private List<Rule> rule;
public List<Rule> getRule() {
return rule;
}
public void setRule(List<Rule> rule) {
this.rule = rule;
}
}
Controller Method :
#RequestMapping(value = "/updateAllRules", method = RequestMethod.POST)
public String updateAllRules(#ModelAttribute("ruleForm") RuleForm ruleForm) throws IOException
{
System.out.println(ruleForm); // this prints com.web.model.RuleForm#235f9fcb
System.out.println(ruleForm.getRule()); //this prints null
return "redirect:/admin";
}
Please let me know what i am missing.
UPDATE 1:
Made changes as suggested. My new HTML form is as below
<form method="POST" th:action="#{/updateAllRules}" th:object="${ruleForm}">
<table>
<thead>
<tr>
<th>S No</th>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr th:each="rule,iteration : ${ruleForm}">
<td th:field="*{rule[__${iteration.index}__].id}"></td>
<td><input type="text" th:field="*{rule[__${iteration.index}__].title}"></td>
<td><input type="text" th:field="*{rule[__${iteration.index}__].body}"></td>
</tr>
</tbody>
</table>
<br>
<input type="submit" value="Update All">
</form>
On making these changes following exception is being received when the page loads.
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'rule' cannot be found on object of type 'java.util.ArrayList' - maybe not public?
Please see that i am sending original list in model attribute "ruleForm" on page load. Once page loads the data and user make changes , i want to POST complete table back to controller.
Forms should have a th:object, rather than a th:field:
<form method="POST" th:action="#{/updateAllRules}" th:object="${ruleForm}">
Instead of using th:name and th:value, you should instead be using th:field which does both of those for you. Fields also should be specified using the *{...} syntax, which assumes the th:object automatically.
<input type="text" th:field="*{rule[__${iteration.index}__].title}" />
Everything else looks correct to me.

Spring MVC Request Param

I have a login page with form action of j_security_check. As of now this form just have two fields namely username
and password. I want to add a new dropdown to this form and collect the selected value in controller using
#RequestParam. For some reason I am not able to pass this dropdown value from JSP to my controller as its throwing the
exception: MissingServletRequestParameterException (Which occurs anytime a request param is missing).
In the code below I added the Visuals dropdown. Do I need to use Spring:Bind tag here?
Also on successful login, the control is directed to a controller with request mapping /controller1.html and this is where
I am trying to collect the dropdown value.
<form name="appLogin" action="j_security_check" method="POST">
<table width="100%">
<tr>
<td align="center">
<table>
<tr>
<td>Username: </td>
<td><input id="userName" name="j_username" value=""/></td>
</tr>
<tr>
<td>Password: </td>
<td><input name="j_password" type="password" value="" /></td>
</tr>
<tr>
<td>Visual: </td>
<td><Select name="visuals" id="visuals"/>
<option value="S1">S1</option>
<option value="S2">S2</option>
<option value="S3">S3</option>
<option value="S4">S4</option>
</Select>
</td>
</tr>
</table>
<table>
<tr>
<td>
<button type="submit" name="submit" value="Sign In">Sign In</button>
<input type="submit"/>
</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table>
</form>
Controller Code:
#RequestMapping( value = " /controller1.html", method = RequestMethod.GET )
public String setupForm( #RequestParam(value = "visuals", required=false) String visuals,
ModelMap model )
{
List<String> studentNames = new ArrayList<String>();
List<String> teacherNames = new ArrayList<String>();
model.addAttribute("someData", teacherNames);
model.addAttribute("anotherData", studentNames);
model.addAttribute("visuals", visuals);
log.info("Role from Dropdown: " + visuals);
return "school/classTen";
}
You need to create yyour own Filter by extending AbstractAuthenticationProcessingFilter
I don't have the entire code in front of my eyes, but the following article could help you:
http://mark.koli.ch/2010/07/spring-3-and-spring-security-setting-your-own-custom-j-spring-security-check-filter-processes-url.html

Categories