如何使用Spring和ThymeLeaf从前端正确地在后端更新对象?

时间:2018-10-31 12:44:49

标签: java spring-mvc thymeleaf

尝试通过前端模板在后端更新对象时遇到麻烦。

这是我的模板,它使用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>

这是我链接到模板的 JS

 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);
 });

这是应该处理请求的Spring 控制器

@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";
}

好!该代码不会在任何地方中断,但是当我单击“提交”按钮时,JS中的变量作为查询字符串在URL中传播,这不是我想要的。

点击表单的“提交”按钮后我的网址示例:

http://localhost:8080/gustos/edit?gustos=106&newName=Dulce+de+Leche+Granizado&newCat=Dulces+de+Leche

这是我第一次制作Spring App!

我的问题是,如何以正确的方式将信息发送到控制器?如果不是这样,人们通常如何更新对象? :(

编辑:期望值正常,表示JS工作正常。问题是将值发送到后端!表单以查询字符串的形式发送它们,这不是我所需要的,查询字符串上分配的值也没有问题

2 个答案:

答案 0 :(得分:2)

在您的方案中,您尝试形成路径参数URL

1。您可以直接在表单元素中指定操作属性,而不是路径参数

<form id="formUpdate" method="GET" action="http://localhost:8080/gustos/edit">

方法属性可以根据需要进行 GET POST

和newCat Select框一样

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

在后端,您可以使用 @RequestParam 获取参数值

@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。另一种方法,使用 form字段值构造一个 JSON 字符串(就像您对路径参数所做的一样),在提交表单时将此JSON字符串发送到后端通过 ajax通话。 在服务层上,将此JSON字符串保持为 Java bean (如果bean结构与JSON匹配,Spring Boot将通过 @RequestBody 批注将JSON值与bean字段绑定)。< / p>

答案 1 :(得分:1)

我建议您在表单中使用th:object。提交表单时,这会立即创建给定类型的对象。因此,假设您的对象是Gusto类型。如果要从头开始创建新实体,则可以在控制器中添加此方法,该方法将返回类型为Gusto的新实体。

新模型属性

// 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();}

表格

现在,您可以使用th:object="${newGusto}"形式的表单来使用此实体。这将为您创建一个新实体,您可以将字段映射到该实体。

为此,您需要在表单中添加以下一个元素。

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

与当前代码唯一的区别是,在选择和输入中添加了th:field元素,并添加了th:object。这些输入和选择中的每一个都会自动将每个字段映射到您刚刚在表单中创建的新实体。

控制器

现在,对于您的控制器,您需要对其进行以下更改。

@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";
}

当然,就您而言,更改jquery很重要。我们现在不想更改URL。我们只想提交表格。因此,必须删除以下代码。

$('#btn-submit').on('submit', (e) => {
    e.preventDefault();
    var url = idGusto + " '/edit' + '/' "+ newName + '/' + newCatId;
    $('#formUpdate').attr('action', url);
});