I have a problem and I don't know how to think about it anymore.
I have a window that shows a list of activity types in a table that loads from BD. I have several action buttons set for each row, including delete and edit. The problem that appears to me is that when I give any of the two buttons, they always call the POST method. I have both with the PUT and the DELETE but they do not go through there and always go to the POST.
I put the controller and html code to see if someone sees something that is being overlooked.
Class Tipo_Actividad_ServicioController:
#Controller
public class Tipo_Actividad_ServicioController {
#Autowired
private Tipo_Actividad_ServicioService tipo_Actividad_ServicioServcie;
#RequestMapping(value = "/tipo_actividad_servicio", method = RequestMethod.GET)
public String findAll(Model model) {
extracted(model);
return "tipo_actividad_servicio";
}
// Guardar Tipo_Actividad_Servicio
#RequestMapping(value = "/tipo_actividad_servicio", method = RequestMethod.POST)
public String save(Tipo_Actividad_Servicio tipo_Actividad_Servicio, Model model) {
tipo_Actividad_ServicioServcie.save(tipo_Actividad_Servicio);
extracted(model);
return "tipo_actividad_servicio";
}
#RequestMapping(value = "/tipo_actividad_servicio", method = RequestMethod.PUT)
public String saveById(#RequestParam int id, Model model) {
Tipo_Actividad_Servicio tipo_Actividad_Servicio = tipo_Actividad_ServicioServcie.findById(id);
if(tipo_Actividad_Servicio.isActivo())
tipo_Actividad_Servicio.setActivo(false);
else
tipo_Actividad_Servicio.setActivo(true);
tipo_Actividad_ServicioServcie.save(tipo_Actividad_Servicio);
extracted(model);
return "tipo_actividad_servicio";
}
#RequestMapping(value = "/tipo_actividad_servicio", method = RequestMethod.DELETE)
public String deleteById(#RequestParam int id, Model model) {
tipo_Actividad_ServicioServcie.deleteById(id);
extracted(model);
return "tipo_actividad_servicio";
}
private void extracted(Model model) {
model.addAttribute("tipos_actividad_servicio", tipo_Actividad_ServicioServcie.findAll());
model.addAttribute("tipo_actividad_servicio", new Tipo_Actividad_Servicio());
}
}
And the HTML table that calls the delete method.
<tbody>
<tr th:each="familia,iterStat : ${tipos_actividad_servicio}" th:class="${iterStat.odd}? 'odd'">
<td th:text="${familia.id}" style="display:false"></td>
<td th:text="${familia.nombre}"></td>
<td th:text="${familia.tipo}"></td>
<td th:text="${familia.observaciones}"></td>
<td style="display: flex; justify-items: center; align-items: center;">
<div class="btn-group">
<button type="button" class="text-white btn .btn-sm btn-warning" data-toggle="modal" data-target="#modal-lg">
Editar
</button>
<form style="margin: 0px;" th:action="#{/tipo_actividad_servicio}" th:method="put">
<input type="hidden" name="id" th:value="${familia.id}">
<button class="text-white btn .btn-sm btn-success" th:unless="${familia.activo}" type="submit">
Activar
</button>
<button class="text-white btn .btn-sm btn-secondary" th:if="${familia.activo}" type="submit">
Desactivar
</button>
</form>
<form style="margin: 0px;" th:action="#{/tipo_actividad_servicio}" th:method="delete">
<input type="hidden" name="id" th:value="${familia.id}">
<button class="text-white btn .btn-sm btn-danger" th:if="${familia.activo}" type="submit">
Eliminar
</button>
</form>
</div>
</td>
</tr>
</tbody>
This is what the console shows me when it calls the method:
Hibernate: update tipo_actividad_servicio set activo=?, nombre=?, observaciones=?, tipo=? where id=?
When I inspect the form from firefox it tells me that the method is post and that it is going to call the PUT or DELETE ...
<form style="margin: 0px;" action="/tipo_actividad_servicio" method="post">
<input type="hidden" name="_method" value="put">
<input type="hidden" name="id" value="2">
<button class="text-white btn .btn-sm btn-secondary" type="submit">
Desactivar
</button>
</form>
The truth is that I no longer know exactly what to do and what to try, if someone could tell me why it doesn't eliminate ...
Thank you.
If you are using Boot 2.3.X then make sure you have enabled the hidden http method filter, spring.mvc.hiddenmethod.filter.enabled=true. This filter is no longer enabled automatically as of 2.3.X. This filter will look at the _method attribute and direct the request to the appropriate controller method.
Related
I get an Internal Server Error, status=500: java.lang.NumberFormatException
The reason seems to be that my form data, sent via name attribute is not intercepted by #RequestMapping or HttpServletRequest doesn't work..
Here I try to pass the data:
<form action="/tankbeurt" method="get" style="padding: 5px;">
<div style="padding: 10px;">
<label for="huidig">Huidige kilometerstand</label>
<input type="text" name="huidig" id="huidig"></div>
<div style="padding: 10px;">
<label for="vorig">Vorige kilometerstand</label>
<input type="text" name="vorig" id="vorig"></div>
<div style="padding: 10px;">
<label for="liter">Hoeveel liter heb je bijgetankt</label>
<input type="text" name="liter" id="liter"></div>
<div><input type="submit" value="Bereken Verbruik"></div>
And I try to intercept it in the mainController:
#Controller
public class MainController {
#RequestMapping("/tankbeurt")
public String gegevens(HttpServletRequest request, Model model){
int huidigeKm = Integer.parseInt("huidig");
System.out.println(huidigeKm);
int vorigeKm= Integer.parseInt("vorig");
double liter= Double.parseDouble("liter");
Tankbeurt tankinformatie = new Tankbeurt(vorigeKm,huidigeKm,liter);
model.addAttribute("informatieTanken",tankinformatie);
return "tankbeurt";
}
Thankyou for your help. I don't see the problem.
Integer.parseInt("huidig");
You are trying to parse string "huidig" to integer. That's the cause of exception. Try looking for some method that extracts property from the model, like "model.getAttribute("huidig")".
I have a SpringBoot app. with this thymelaf template, that works fine when submitting:
<div class="form-group required-control">
<label for="gre">GRE</label>
<input id="gre" type="checkbox" name="gre" th:checked="*{gre}" th:onclick="submit()" />
</div>
but when I add another checkbox, It always take in account the first one, regardless which one I click
<div class="form-group required-control">
<label for="gre">GRE</label>
<input id="gre" type="checkbox" name="gre" th:checked="*{gre}" th:onclick="submit()" />
<label for="gre2">GRE2</label>
<input id="gre2" type="checkbox" name="gre2" th:checked="*{gre2}" th:onclick="submit()" />
</div>
There is no technical problem here. I think there is a problem with your submit() function, because I created a normal form and tried your same instance, and all selection combinations worked correctly.
I am adding the entity, controller and html files respectively for example.
public class Example {
private boolean gre;
private boolean gre2;
public Example() {
}
// getter/setter ...
}
#Controller
#RequestMapping("/example")
public class ExampleController {
#GetMapping("/create")
public String createExample(Model model) {
model.addAttribute("example", new Example());
return "example-form";
}
#PostMapping("/insert")
public String insertExample(Model model, Example example) {
model.addAttribute("example", example);
return "example-form";
}
}
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<form action="/example/insert" method="post" th:object="${example}">
<div class="form-group required-control">
<label for="gre">GRE</label>
<input id="gre" type="checkbox" name="gre" th:checked="*{gre}" />
<label for="gre2">GRE 2</label>
<input id="gre2" type="checkbox" name="gre2" th:checked="*{gre2}" />
</div>
<button type="submit">Submit Form</button>
</form>
</div>
</body>
</html>
If you don't want to add an attribute into the Model, you can receive checkbox condition via HttpServletRequest.
#GetMapping("/create")
public String createExample() {
return "example-form";
}
#PostMapping("/insert")
public String insertExample(User user, HttpServletRequest request) {
user.setGre(request.getParameter("gre") != null);
user.setGre2(request.getParameter("gre2") != null);
userServiceImp.updateUser(editedUser); //for example updating user in database
return "/";
}
HTML will be like this:
<form th:action="/insert" method="post">
<div class="form-group required-control">
<label>GRE</label>
<input type="checkbox" name="gre"/>
<label>GRE 2</label>
<input type="checkbox" name="gre2"/>
</div>
<button type="submit">Submit Form</button>
</form>
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";
}
Hibernate Validator doesn't show error message. What did i miss? Please see my code below.
Here is a dependency:
<!-- Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
And Entity with annotated column:
#Entity
#Table(name = "transport")
public class Transport {
....
#NotEmpty
#Column(name = "name")
private String name;
....
}
Here are methods from controller:
//show all and add form
#RequestMapping (value = "/admin/transports", method = RequestMethod.GET)
public String findAll(ModelMap map){
List<Transport> transports = transportService.findAll();
map.put("transport", new Transport());
map.put("transports", transports);
return "admin/transports/list";
}
//add new
#RequestMapping(value = "/admin/transport/add", method = RequestMethod.POST)
public String addTypeShop(#ModelAttribute("type") #Valid Transport transport, BindingResult result) {
if (result.hasErrors()) {
return "redirect:/admin/transports";
} else {
this.transportService.addTransport(transport);
return "redirect:/admin/transports";
}
}
And jsp page:
<form:form role="form" action="/admin/transport/add" method="post" commandName="transport">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label for="name">Name</label>
<form:input type="text" path="name" class="form-control input-sm" id="name" autofocus="true"/>
<form:errors path="name"/>
</div>
</div>
<input type="submit" class="btn btn-sm btn-primary" value="Add" onclick="loading()"/>
</form:form>
You do not have any code showing the errors back to the end user.
Please see the following link for an example:
http://www.mkyong.com/spring-mvc/spring-mvc-form-errors-tag-example/
Also, It doesn't look like you actually set your command object in your form. You might not have shown that code though.
Small side note, I would not do a redirect if you have validation errors, just send them directly back to the page they came from.
EDIT
After further review, I do see that you have . Normally this goes outside and above the form itself.
<form:errors path="transport"/>
<form:form role="form" action="/admin/transport/add" method="post" commandName="transport">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label for="name">Name</label>
<form:input type="text" path="name" class="form-control input-sm" id="name" autofocus="true"/>
</div>
</div>
<input type="submit" class="btn btn-sm btn-primary" value="Add" onclick="loading()"/>
</div>
</form:form>
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 ...
}