Thymeleaf динамически создает формы, используя th:each

Я хотел бы знать, как создавать формы, использующие th:object для каждого объекта, зацикленного в th:each. Например, у меня есть следующий код.

HTML

<th:block th:each = "store: ${stores}">
    <form th:object = "${store}" th:action = "@{/modify-store}">
        <input th:field = "*{idStorePk}"/>
        <input th:field = "*{name}"/>
        <input th:field = "*{phoneNumber}"/>
        <button type = "submit">Modify</button>
    </form>
</th:block>

Контроллер

@RequestMapping(value = "/stores")
public String getIndex(Model model) {
    model.addAttribute("stores", storeService.getAllStores());
    return "store";
}

Итак, я хотел бы добавить форму для каждого объекта, но кажется, что это невозможно, и я получаю следующую ошибку.

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'store' available as request attribute

Итак, я решил добавить @ModelAttribute в свой контроллер, но не могу вернуть реальный магазин.

@ModelAttribute("store")
public Store getStore(Store store) {
    return store;
}

При таком подходе все мои формы имеют нулевые значения. Я также пытался добавить @PathVariable, но не могу связать его с помощью th:object. Есть ли решение для этого?

Вы не отправляете простой (пустой) объект хранилища в store. вместе со списком stores также отправьте store .

soorapadman 01.02.2019 07:24

Мне не нужен простой пустой магазин, но для каждого магазина я хочу каждый, если это значения. Кроме того, я пробовал несколько способов, включая отправку пустого хранилища, но я все еще не могу получить значения каждого хранилища с помощью th:object.

Alain Cruz 04.02.2019 18:34

Ваша проблема очевидна. Модель настроена неправильно. Все еще удивляетесь, почему вы повторяете формы.

soorapadman 04.02.2019 18:38

Я хочу создать форму изменения для каждого магазина динамически. Вот почему я повторяю каждый магазин и создаю новый магазин. Проблема очевидна, решения нет. Использование th:object не представляется возможным, поэтому я и спросил.

Alain Cruz 04.02.2019 18:41

Я также застрял на похожей вещи: я пытаюсь создать несколько форм на странице, используя th:each , но не получаю «Ни BindingResult, ни простой целевой объект для имени bean-компонента« XYS », доступного в качестве атрибута запроса». Вы смогли это решить?

Pankaj Vatsa 26.10.2019 00:18

@PankajVatsa в некотором роде да, но это может показаться обходным путем. Я опубликую это как ответ.

Alain Cruz 26.10.2019 00:20

@AlainCruz Пожалуйста, опубликуйте ответ ..

Pankaj Vatsa 26.10.2019 00:21

@PankajVatsa только что сделал. Надеюсь, поможет. Не забудьте использовать точное имя имен атрибутов вашей модели.

Alain Cruz 26.10.2019 01:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
8
1 686
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы отправляете магазины в свой контроллер в атрибуте модели, а на втором контроллере, где вы отправляете форму, вы используете хранить, поэтому вы получаете эту ошибку. Поэтому исправьте орфографическую ошибку на любом из ваших контроллеров. Нравится :-

@RequestMapping(value = "/stores")
public String getIndex(Model model) {
    model.addAttribute("stores", storeService.getAllStores());
    return "store";
}

И ваш второй контроллер, на который вы отправляете форму, будет таким:

@ModelAttribute("stores")
public Store getStore(Store store) {
    return store;
}

Я все еще получаю нулевые значения для каждого магазина. Мне нужно динамически заполнять ввод каждой формы с помощью th:field.

Alain Cruz 04.02.2019 18:35
Ответ принят как подходящий

Так что для тех, кто застрял на подобной проблеме. Я нахожу обходной путь, который может вам помочь. Во-первых, нельзя использовать th:object, он его просто не порежет. Вместо этого сделайте следующее.

<th:block th:each = "store: ${stores}">
    <form class = "store-form" th:action = "@{/modify-store}">
        <input th:name = "idStorePk" th:value = "${store.idStorePk}"/>
        <input th:name = "name" th:value = "${store.name}"/>
        <input th:name = "phoneNumber" th:value = "${store.phoneNumber}"/>
        <button class = "submit-button" type = "submit">Modify</button>
    </form>
</th:block>

Затем просто добавьте что-то подобное в контроллер.

@PostMapping(value = "/modify-store")
@ResponseBody
public boolean deleteEntry(@ModelAttribute Store store) throws Exception {
    // Your code here...
    return true;
}

Если вы хотите отправить его асинхронно, вам нужно будет добавить код JS, чтобы он работал. Это должно выглядеть примерно так, как показано ниже.

const forms = document.querySelectorAll('.store-form');
forms.forEach(form => {
   form.addEventListener('submit', event => {

   // Stop the normal form submit triggered by the submit button
   event.preventDefault();

   const formInputs = form.getElementsByTagName("input");
   let formData = new FormData();
   for (let input of formInputs) {
       formData.append(input.name, input.value);
   }

   fetch(form.action,
   {
        method: form.method,
        body: formData
   })
   .then(response => response.json())
   .then(data => console.info(data))
   .catch(error => console.info(error.message))
   .finally(() => console.info("Done"));
});

Этот ответ помог разблокировать меня. Спасибо!

Pankaj Vatsa 30.10.2019 21:38

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