Reputation: 364
I'm getting trouble trying to update my Object in the back-end via a front-end template.
This is my template, it uses ThymeLeaf
<form id="formUpdate" method="put">
<div class="row">
<div class="col s12">
<h2> Modificar Gustos</h2>
</div>
</div>
<div class="divider"></div>
<div class="row">
<label for="selectGusto">Nombre del gusto a cambiar</label>
<select name="gustos" id="selectGusto">
<option value="-1" selected="selected" disabled="disabled">Lista de Gustos</option>
<option th:each="gusto : ${gustos}" th:text="${gusto.nombre}" th:value="${gusto.id}"> </option>
</select>
</div>
<label for="newName">Nuevo Nombre</label>
<input type="text" name="newName" id="newName" />
<div class="row">
<label for="selectCat">Elegir nueva Categoria</label>
<select name="newCat" id="selectCat">
<option value="-1" selected="selected" disabled="disabled">Nueva Categoria</option>
<option value="Dulces de Leche">Dulce de Leche</option>
<option value="Cremas">Cremas</option>
<option value="Chocolates">Chocolates</option>
<option value="Frutales">Frutales</option>
</select>
</div>
<button type="submit" id="btn-submit" class="button">Modificar</button>
</form>
This is my JS linked to the template:
var newCatId;
var idGusto;
var newName;
$('#selectCat').on('change', () => {
var value = $('#selectCat').val();
if(value === "Dulces de Leche") {
newCatId = 1;
}
else if(value === "Cremas") {
newCatId = 2;
}
else if(value === "Chocolates") {
newCatId = 3;
}
if(value === "Frutales") {
newCatId = 4;
}
console.log('newCatId: ' + newCatId);
console.log('idGusto ' + idGusto);
console.log('newName: ' + newName);
});
$('#selectGusto').on('change', function() {
idGusto = $(this).val();
});
newName = $('#newName').val();
$('#btn-submit').on('submit', (e) => {
e.preventDefault();
var url = idGusto + " '/edit' + '/' "+ newName + '/' + newCatId;
$('#formUpdate').attr('action', url);
});
And this is the Spring controller that should handle the request:
@RequestMapping(value = "/gustos/{id}/edit/{newName}/{newIdCat}")
public String updateGustoById(@PathVariable("id") int id, @PathVariable("newIdCat") int newIdCat, @PathVariable("newName") String newName){
Gusto gusto = gustoService.findGustoById(id);
gusto.setNombre(newName);
gusto.setIdCategoria(newIdCat);
gustoService.update(gusto);
return "redirect:/gustos/edit";
}
Ok !! This code doesn't breaks anywhere but when I click on the submit button the variables in the JS travel in the URL as a Query String, that's not what I want to.
Example of my URL after clicking the form's submit button:
http://localhost:8080/gustos/edit?gustos=106&newName=Dulce+de+Leche+Granizado&newCat=Dulces+de+Leche
This is my first time making a Spring App!
My question is, how can I send the information to the controller in the right way? How do people normally update an Object if is not like this? :(
EDIT: The expected values are OK, that means the JS is working OK. The problem is sending the values to the back-end !! The form is sending them as a Query String and that's not what I need, neither the assigned values on the Query String are fine
Upvotes: 0
Views: 1479
Reputation: 161
In Your Scenario, Your trying to form path param URL
1.Instead of path params you can directly specify the action attribute in form element
<form id="formUpdate" method="GET" action="http://localhost:8080/gustos/edit">
method attribute can be GET or POST according to your need.
And newCat Select box like
<select name="newCat" id="selectCat">
<option value="-1" selected="selected" disabled="disabled">Nueva Categoria</option>
<option value="1">Dulce de Leche</option>
<option value="2">Cremas</option>
<option value="3">Chocolates</option>
<option value="4">Frutales</option>
</select>
In Backend you can use @RequestParam to get paramter values
@RequestMapping(value = "/gustos/edit")
public String updateGustoById(@RequestParam(value="gustos") int id, @RequestParam(value="newCat")
int newIdCat, @RequestParam(value="newName") String newName)
{
Gusto gusto = gustoService.findGustoById(id);
gusto.setNombre(newName);
gusto.setIdCategoria(newIdCat);
gustoService.update(gusto);
return "redirect:/gustos/edit";
}
2.Another approach, Construct a JSON string with form field values (like you did for path params), While Submitting the form send this JSON string to back end through ajax call. On your service layer keep this JSON String as Java beans (Spring Boot bind JSON values with the bean fields through @RequestBody annotation, if bean structure matched with the JSON).
Upvotes: 3
Reputation: 5097
I would recommend using th:object
in your form. This creates an object of a given type instantly when you submit your form. So, let's say your object is of type Gusto. If you want to create a new entity from scratch, you could add this method in your controller that will return a new entity of type Gusto.
New Model Attribute
// 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 Gusto entity.
@ModelAttribute(value = "newGusto")
public Gusto newGusto() {return new Gusto();}
Form
So now, you can use this entity in a form using th:object="${newGusto}"
. This will create a new entity for you, which you might mapped fields to it.
In order to do so you would need to add following one elements to your form.
<form action="/gustos/edit/" id="formUpdate" method="put" th:object="${newGusto}">
<div class="row">
<div class="col s12">
<h2> Modificar Gustos</h2>
</div>
</div>
<div class="divider"></div>
<div class="row">
<label for="selectGusto">Nombre del gusto a cambiar</label>
<select th:field="*{id}" name="gustos" id="selectGusto">
<option value="-1" selected="selected" disabled="disabled">Lista de Gustos</option>
<option th:each="gusto : ${gustos}" th:text="${gusto.nombre}" th:value="${gusto.id}"> </option>
</select>
</div>
<label for="newName">Nuevo Nombre</label>
<input th:field=*{nombre} type="text" name="newName" id="newName" />
<div class="row">
<label for="selectCat">Elegir nueva Categoria</label>
<select th:field="*{categoria} name="newCat" id="selectCat">
<option value="-1" selected="selected" disabled="disabled">Nueva Categoria</option>
<option value="Dulces de Leche">Dulce de Leche</option>
<option value="Cremas">Cremas</option>
<option value="Chocolates">Chocolates</option>
<option value="Frutales">Frutales</option>
</select>
</div>
<button type="submit" id="btn-submit" class="button">Modificar</button>
</form>
The only difference you will find with your current code, is the added th:field
elements in your selects and inputs and the th:object
. Each one of these inputs and selects, will automatically mapped each field to the new entity you just created in your form.
Controller
Now for your controller you would need to change it for the following.
@RequestMapping(value = "/gustos/edit/")
public String updateGusto(@ModelAttribute("newGusto") Gusto gustoToUpdate){
Gusto gusto = gustoService.findGustoById(gustoToUpdate.getId());
gusto.setNombre(gustoToUpdate.getNombre());
gusto.setIdCategoria(gustoToUpdate.getCategoria());
gustoService.update(gusto);
return "redirect:/gustos/edit";
}
Of course, in your case, it is important that you change your jquery
. We don't want to change the URL now. We just want to submit the form. So the following code, would have to be removed.
$('#btn-submit').on('submit', (e) => {
e.preventDefault();
var url = idGusto + " '/edit' + '/' "+ newName + '/' + newCatId;
$('#formUpdate').attr('action', url);
});
Upvotes: 1