How do you send a value of a button to a Controller?
I have the following HTML
<form th:method="POST" th:action="#{'/bet/addGame/{gameId}'
(gameId = ${game.getGameId()})}">
<th scope="row"><button class="btn btn-primary" name="konTip" value="1" th:text="${game.getCoef1()}">1.15</button></th>
<th scope="row"><button class="btn btn-primary" name="konTip" value="X" th:text="${game.getCoefx()}">4.20</button></th>
<th scope="row"><button class="btn btn-primary" name="konTip" value="2" th:text="${game.getCoef2()}">3.40</button></th>
</form>
As you can see from the image I have three buttons under the "1, X and 2" row I want to pass the value of the button on which the user clicks to the Controller on the Back-end say like a RequestParam for example but I have no idea how to do this.
I tried to add JS to it but I can't really understand the thymeleaf documentation very well
This is my Controller Class
#PostMapping("/addGame/{gameId}")
public String addGameToTicket(#PathVariable Integer gameId, Model model, HttpServletRequest request) {
User user = (User) request.getSession().getAttribute("user");
Ticket ticket = this.ticketService.findTicketByUser(user.getUsername())
.orElseThrow(()->new TicketNotFoundUserNameException(user.getUsername()));
Game gameToAdd = this.gameService.findById(gameId);
this.ticketService.addGame(user.getUsername(), gameId);
return "redirect:/bet";
}
Related
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.
I am trying to fire onClick event and Spring controller one by one.
In the click event of the button, I set a hidden field and then I want the controller to be executed AND the hidden field to be available in it. Here is my code for the JSP and the Spring Controller
JSP
<html:hidden property="MenuID" name="MenuID" id="hidMenuID" />
<c:forEach items="${menus}" var="menu" >
<tr class="cartItem">
<td align="left" >${MenuId}</td>
td align="right"><input type="text" name="menu_name" value="${Name}"/></td>
<td align="right"><input type="text" name="menu_price" value="${MenuPrice}"/></td>
<td align="right"><input type="submit" class="button" name="add_menu" value="Add" onclick="return SetMenuID();"></td>
<td align="right"><input type="submit" class="button" name="remove_menu" value="Remove" onclick="return SetMenuID();"></td>
</tr>
</c:forEach>
JavaScript
<script type="text/javascript">
function SetMenuID()
{
var MenuID = document.getElementById('hidMenuID');
MenuID.value = 'The new value';
return true;
}
</script>
Spring MVC
#RequestMapping(params = "add_menu", method = RequestMethod.POST)
public ModelAndView AddMyMenu(#RequestParam("MenuID") String menu_id, Model model, #ModelAttribute("cart") ArrayList<Menu> mycart)
{
int nMenuId = Integer.parseInt(menu_id);
Menu menu = m_arrMenus.get(nMenuId);
model.addAttribute("menus", GetMenus());
mycart.add(menu);
return new ModelAndView("edit_menu");
}
As you might guess, I am populating data from database. I have an onClick function associated with each ADD button. I set hidden field in thid function and want it to be available in my controller. But a runtime exception comes that
Error Status 400 - Required string MenuID is not present
What should I do to achieve similar result ? Thanks for any input.
#RequestParam expects a parameter my name in the request url.
Since your form is submitted and there are no request param that the action recieves. This is a reason you are getting 400 http error from server.
See the difference between #RequestParam vs #PathVariable
So either change the #RequestParam annotation or add (required = false) to it.
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 ...
}
i have a html table:
<div id="connInfoMainDiv">
<table>
<tr>
<td>Connection</td>
<td>Action</td>
</tr>
<tr>
<td>On</td>
<td>
<input type"radio" checked="checked" value="0" name="rs[0].selection"> off
<input type"radio" checked="checked" value="1" name="rs[0].selection"> on
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" name="btnSubmit" text="submit" /></td>
</tr>
</table>
</div>
here is my java controller:
#RequestMapping(method=RequestMethod.GET, value="/conn/ajax")
public String getAjaxConnInfo(#ModelAttribute("ConnForm")ConnForm connForm,
BindingResult result,
ModelMap model,
final RedirectAttributes redirectAttributes) {
.....//get data from web service
model.addAttribute("connForm", connForm);
return "/conn/ajax";
}
here is my connForm:
public class ConnForm {
private List<connT> connList;
}
here is my connT class:
public class connT {
private int connStatus = 0; // 0=off, 1,on
private boolean radioSelected = false;
}
here is my ajax which does the polling:
$(document).read(function() {
setInterval(getConnInfo, 2000);
});
function getConnInfo() {
$.get("http://domain.com/conn/ajax", function(data) {
$("#connInfoMainDiv").html(data);
});
}
i implemented a ajax polling to constantly update the data on this page. what happen in the controller is it will get the data from database, set it to the object and return it to the jsp template. i previously asked here
here is the problem im encountering:
- Connection is off, radio button "off" is checked
- i clicked radio button "on".
- before i could click submit, the ajax kicks in. when this happen, it updates the page and the radio button "off" is checked.
how can i keep the radio button "on" checked??
What's the best practice to pre-populate an object before saving this object with hibernate?
What i've done:
My controller:
//The Form
#RequestMapping(value = "user/{id}/edit", method = RequestMethod.GET)
public String edit(#PathVariable("id") Long userId, ModelMap modelMap) {
modelMap.addAttribute("user", userService.find(userId));
return "user/userEdit";
}
//Updating database
#RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(#ModelAttribute("user") #Valid User user, BindingResult result,
RedirectAttributes redirectAttrs) {
if (result.hasErrors()) {
return "user/userEdit";
}else{
userService.update(user);
redirectAttrs.addFlashAttribute("message", "Success");
return "redirect:user/userEdit";
}
}
It works if i make a form containing all fields (username, password and id) , but what should i do if i want the user to update only the password?
Since i have a #NotEmpty at username, i get an error that username is null, since its not in the form, but i dont want to put the username field, just the password.
My html form:
<c:url var="url" value="/user/edit" />
<form:form method="post" action="${url}" modelAttribute="user" class="form-horizontal">
<form:hidden path="id"/>
<form:hidden path="version"/>
<fieldset>
<div class="control-group">
<form:label cssClass="control-label" path="password"><spring:message code="user.label.password"/>: </form:label>
<div class="controls">
<form:input cssClass="input-xlarge" path="password" />
</div>
<form:errors path="password"/>
</div>
<div class="control-group">
<form:label cssClass="control-label" path="userRole"><spring:message code="user.label.role"/>: </form:label>
<div class="controls">
<form:select path="userRole">
<form:options items="${userRoleList}" itemValue="id" itemLabel="name"/>
</form:select>
</div>
<form:errors path="userRole"/>
</div>
<div class="control-group">
<form:label cssClass="control-label" path="costumer.id"><spring:message code="user.label.costumer"/>: </form:label>
<div class="controls">
<form:select path="costumer.id">
<form:options items="${costumerList}" itemValue="id" itemLabel="name"/>
</form:select>
</div>
<form:errors path="costumer.id"/>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save changes</button>
<a class="btn cancel link" href="<c:url value="/user" />">Cancel</a>
</div>
</fieldset>
</form:form>
I tried using #Sessionattributes, but it doesnt work well if i try to
edit two or more users using browser tabs.
I tried using property editors, but didnt work with #ModelAtrribute
User user.
I tried using convertors but didnt work.
Is the only way to make a User user = userService.find(id) first, and then set the updated values? Something like:
#RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(#RequestParam("password") String password, BindingResult result, RedirectAttributes redirectAttrs) {
User user = userService.find(id);
if (password == null{
return "user/userEdit";
}else{
user.setPassword("password");
userService.update(user);
redirectAttrs.addFlashAttribute("message", "Success");
return "redirect:user/userEdit";
}
}
Which seens wrong, because there is no validation.
An alternate way, that I think is less messy and accident-prone, is to create a class that models the UI form, for example
public class EditUserForm {
// getters and setters for password and other fields...
}
and in the controller's update(EditUserForm,...) method, you simply map any fields populated by the user in the EditUserForm to the instance of User you wish to update.
In the code you posted it's obviously clear that you need some external helper classes to associate with your GUI side updating before you implement the move-control and persistence operations.
I've run into this problem too, if there's only a couple fields I use your second example and validate the fields one by one. Otherwise, you're going to have to do what the other posters have said and make a new class to match your form.
Try to use:
#PrePersist
#PreUpdate
public void prepare(){
//DO SOMETHING WITH YOUR ENTITY
//For example: if(name==null){ name="MYNAMEVALUE";}
}