Я хотел бы знать, как создавать формы, использующие 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. Есть ли решение для этого?
Мне не нужен простой пустой магазин, но для каждого магазина я хочу каждый, если это значения. Кроме того, я пробовал несколько способов, включая отправку пустого хранилища, но я все еще не могу получить значения каждого хранилища с помощью th:object.
Ваша проблема очевидна. Модель настроена неправильно. Все еще удивляетесь, почему вы повторяете формы.
Я хочу создать форму изменения для каждого магазина динамически. Вот почему я повторяю каждый магазин и создаю новый магазин. Проблема очевидна, решения нет. Использование th:object не представляется возможным, поэтому я и спросил.
Я также застрял на похожей вещи: я пытаюсь создать несколько форм на странице, используя th:each , но не получаю «Ни BindingResult, ни простой целевой объект для имени bean-компонента« XYS », доступного в качестве атрибута запроса». Вы смогли это решить?
@PankajVatsa в некотором роде да, но это может показаться обходным путем. Я опубликую это как ответ.
@AlainCruz Пожалуйста, опубликуйте ответ ..
@PankajVatsa только что сделал. Надеюсь, поможет. Не забудьте использовать точное имя имен атрибутов вашей модели.




Вы отправляете магазины в свой контроллер в атрибуте модели, а на втором контроллере, где вы отправляете форму, вы используете хранить, поэтому вы получаете эту ошибку. Поэтому исправьте орфографическую ошибку на любом из ваших контроллеров. Нравится :-
@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.
Так что для тех, кто застрял на подобной проблеме. Я нахожу обходной путь, который может вам помочь. Во-первых, нельзя использовать 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"));
});
Этот ответ помог разблокировать меня. Спасибо!
Вы не отправляете простой (пустой) объект хранилища в
store. вместе со спискомstoresтакже отправьтеstore.