Как правильно обновить объект в серверной части из внешнего интерфейса с помощью spring и 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";
}

Ok !! Этот код нигде не ломается, но когда я нажимаю кнопку отправки, переменные в JS перемещаются по URL-адресу в виде строки запроса, это не то, что я хочу.

Пример моего URL-адреса после нажатия кнопки отправки формы:

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

Я впервые создаю приложение Spring!

У меня вопрос, как я могу правильно отправить информацию контроллеру? Как люди обычно обновляют объект, если это не так? :(

РЕДАКТИРОВАТЬ: ожидаемые значения в порядке, это означает, что JS работает нормально. Проблема заключается в отправке значений в серверную часть !! Форма отправляет их как строку запроса, и это не то, что мне нужно, ни назначенные значения в строке запроса не в порядке

Я не понимаю, зачем вообще используется javascript - почему бы просто не разрешить естественную отправку формы на POST?

Andrew S 31.10.2018 14:03

Не знаю, почему ... хахаха ... Я попробую это сейчас ... Я подумал, что должен сделать это с помощью метода PUT, а форма не приняла put, а затем изменилась ... вы знаете как оно ... Попробую сейчас решение Аравинда. Спасибо :)

Nacho Zve De La Torre 31.10.2018 14:43
0
2
570
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашем сценарии вы пытаетесь сформировать URL-адрес параметра пути

1.Вместо параметров пути вы можете напрямую указать атрибут действия в элементе формы

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

атрибут метода может быть ПОЛУЧАТЬ или ПОЧТА в соответствии с вашими потребностями.

И новое поле выбора кошки, например

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

В Backend вы можете использовать @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. Другой подход, создайте строку JSON с помощью значения полей формы (как вы это делали для параметров пути), при отправке формы отправьте эту строку JSON в серверную часть через вызов ajax. На уровне обслуживания сохраните эту строку JSON как Java beans (Spring Boot связывает значения JSON с полями компонента через аннотацию @RequestBody, если структура компонента соответствует JSON).

Это может сработать !! Спасибо брат ... попробую

Nacho Zve De La Torre 31.10.2018 14:42

Это сработало отлично и узнало о @RequestParam (я не знал, что он существует)! Спасибо и привет из Аргентины :)

Nacho Zve De La Torre 31.10.2018 15:57

Я бы рекомендовал использовать 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);
});

Большое спасибо, Ален, на этот раз я использовал другое решение, потому что оно казалось проще, чем привязка объекта! Только что получил параметры с помощью @RequestParam ... не знал, что смогу это сделать :) Большое спасибо за ваше время

Nacho Zve De La Torre 31.10.2018 15:56

Без проблем! Больше подходов к проблеме всегда хорошо :)

Alain Cruz 31.10.2018 15:57

Другие вопросы по теме